Refactored sub bean logic

This commit is contained in:
Ziver Koc 2017-02-17 17:15:34 +01:00
parent 7c4c536ce5
commit 5b15515432
3 changed files with 108 additions and 120 deletions

View file

@ -151,47 +151,39 @@ public abstract class DBBean {
// Generate the SQL
StringBuilder query = new StringBuilder();
if (this.id == null) {
query.append("INSERT INTO ").append(config.tableName).append(' ');
query.append("INSERT INTO ").append(config.tableName);
StringBuilder sqlCols = new StringBuilder();
StringBuilder sqlValues = new StringBuilder();
for (Field field : config.fields) {
if (!List.class.isAssignableFrom(field.getType())) {
if (sqlCols.length() == 0)
sqlCols.append("(");
else sqlCols.append(", ");
sqlCols.append(DBBeanConfig.getFieldName(field));
if (sqlCols.length() > 0)
sqlCols.append(", ");
sqlCols.append(DBBeanConfig.getFieldName(field));
if (sqlValues.length() == 0)
sqlValues.append("VALUES(");
else sqlValues.append(", ");
sqlValues.append("?");
}
if (sqlValues.length() > 0)
sqlValues.append(", ");
sqlValues.append("?");
}
if (sqlCols.length() > 0) { // Did we generate any query?
query.append(sqlCols).append(") ");
query.append(sqlValues).append(") ");
if (config.fields.size() > 0) { // is there any fields?
query.append(" (").append(sqlCols).append(")");
query.append(" VALUES(").append(sqlValues).append(")");
} else
query.append("DEFAULT VALUES");
} else {
query.append("UPDATE ").append(config.tableName).append(' ');
query.append(" DEFAULT VALUES");
}
else if (config.fields.size() > 0) { // Is there any fields to update?
query.append("UPDATE ").append(config.tableName);
StringBuilder sqlSets = new StringBuilder();
for (Field field : config.fields) {
if (!List.class.isAssignableFrom(field.getType())) {
if (sqlSets.length() > 0)
sqlSets.append(", ");
sqlSets.append(DBBeanConfig.getFieldName(field));
sqlSets.append("=?");
}
if (sqlSets.length() > 0)
sqlSets.append(", ");
sqlSets.append(DBBeanConfig.getFieldName(field));
sqlSets.append("=?");
}
if (sqlSets.length() > 0) { // Did we generate any query?
query.append("SET ").append(sqlSets);
query.append("WHERE ").append(config.idColumn).append("=?");
} else
query = null; // Class has no fields that needs updating
query.append(" SET ").append(sqlSets);
query.append(" WHERE ").append(config.idColumn).append("=?");
}
// Check if we have a valid query to run, skip otherwise
if (query != null) {
if (query.length() > 0) {
String sql = query.toString();
logger.finest("Save Bean(" + c.getName() + ", id: " + this.getId() + ") query: " + sql);
PreparedStatement stmt = db.getPreparedStatement(sql);
@ -209,11 +201,6 @@ public abstract class DBBean {
stmt.setObject(index, null);
index++;
}
// A list of DBBeans
else if (List.class.isAssignableFrom(field.getType()) &&
field.getAnnotation(DBLinkTable.class) != null) {
// Do stuff later
}
// Normal field
else {
Object value = getFieldValue(field);
@ -234,52 +221,50 @@ public abstract class DBBean {
}
// Save sub beans, after we get the parent object id
for (Field field : config.fields) {
if (List.class.isAssignableFrom(field.getType()) &&
field.getAnnotation(DBLinkTable.class) != null) {
if (this.id == null)
throw new SQLException("Unknown parent object id");
for (Field field : config.subBeanFields) {
if (this.id == null)
throw new SQLException("Unknown parent object id");
List<DBBean> list = (List<DBBean>) getFieldValue(field);
if (list != null) {
DBLinkTable linkTableAnnotation = field.getAnnotation(DBLinkTable.class);
String linkTable = linkTableAnnotation.table();
String idCol = (linkTableAnnotation.idColumn().isEmpty() ? config.tableName : linkTableAnnotation.idColumn());
String subIdCol = "id";
List<DBBean> list = (List<DBBean>) getFieldValue(field);
if (list != null) {
DBLinkTable linkTableAnnotation = field.getAnnotation(DBLinkTable.class);
String linkTable = linkTableAnnotation.table();
String idCol = (linkTableAnnotation.idColumn().isEmpty() ? config.tableName : linkTableAnnotation.idColumn());
String subIdCol = "id";
DBBeanConfig subObjConfig = null;
for (DBBean subObj : list) {
// Save the sub bean
if (recursive || subObj.getId() == null)
subObj.save(db);
if (subObj.getId() == null) {
logger.severe("Unable to save field " + c.getSimpleName() + "." + field.getName() + " with " + subObj.getClass().getSimpleName());
continue;
}
// Get the Sub object configuration
if (subObjConfig == null) {
subObjConfig = DBBeanConfig.getBeanConfig(subObj.getClass());
subIdCol = subObjConfig.idColumn;
}
// Save links in link table
String sql;
if (linkTable.equals(subObjConfig.tableName))
sql = "UPDATE " + linkTable + " SET " + idCol + "=? WHERE " + subIdCol + "=?";
else
sql = "INSERT INTO " + linkTable + " (" + idCol + ", " + subIdCol + ") SELECT ?,? " +
"WHERE NOT EXISTS(SELECT 1 FROM " + linkTable + " WHERE " + idCol + "=? AND " + subIdCol + "=?);";
logger.finest("Save sub Bean(" + c.getName() + ", id: " + subObj.getId() + ") query: " + sql);
PreparedStatement subStmt = db.getPreparedStatement(sql);
subStmt.setLong(1, this.id);
subStmt.setLong(2, subObj.getId());
if (subStmt.getParameterMetaData().getParameterCount() > 2) {
subStmt.setLong(3, this.id);
subStmt.setLong(4, subObj.getId());
}
DBConnection.exec(subStmt);
}
}
}
DBBeanConfig subObjConfig = null;
for (DBBean subObj : list) {
// Save the sub bean
if (recursive || subObj.getId() == null)
subObj.save(db);
if (subObj.getId() == null) {
logger.severe("Unable to save field "+ c.getSimpleName()+"."+field.getName() +
" with "+ subObj.getClass().getSimpleName() +" because sub bean id is null");
continue;
}
// Get the Sub object configuration
if (subObjConfig == null) {
subObjConfig = DBBeanConfig.getBeanConfig(subObj.getClass());
subIdCol = subObjConfig.idColumn;
}
// Save links in link table
String sql;
if (linkTable.equals(subObjConfig.tableName))
sql = "UPDATE " + linkTable + " SET " + idCol + "=? WHERE " + subIdCol + "=?";
else
sql = "INSERT INTO " + linkTable + " (" + idCol + ", " + subIdCol + ") SELECT ?,? " +
"WHERE NOT EXISTS(SELECT 1 FROM " + linkTable + " WHERE " + idCol + "=? AND " + subIdCol + "=?);";
logger.finest("Save sub Bean(" + c.getName() + ", id: " + subObj.getId() + ") query: " + sql);
PreparedStatement subStmt = db.getPreparedStatement(sql);
subStmt.setLong(1, this.id);
subStmt.setLong(2, subObj.getId());
if (subStmt.getParameterMetaData().getParameterCount() > 2) {
subStmt.setLong(3, this.id);
subStmt.setLong(4, subObj.getId());
}
DBConnection.exec(subStmt);
}
}
}
} catch (SQLException e) {
throw e;

View file

@ -28,6 +28,7 @@ import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
/**
* A Class that contains information about a bean
@ -38,23 +39,23 @@ class DBBeanConfig{
/** The name of the table in the DB **/
protected String tableName;
public String tableName;
/** The name of the id column **/
protected String idColumn;
/** All the fields in the bean **/
protected ArrayList<Field> fields;
public String idColumn;
/** All normal fields in the bean **/
public ArrayList<Field> fields = new ArrayList<>();
/** All sub bean fields in the bean **/
public ArrayList<Field> subBeanFields = new ArrayList<>();
private DBBeanConfig(){
fields = new ArrayList<>();
}
private DBBeanConfig(){ }
/**
* @return the configuration object for the specified class
*/
protected static DBBeanConfig getBeanConfig(Class<? extends DBBean> c){
public static DBBeanConfig getBeanConfig(Class<? extends DBBean> c){
if( !beanConfigs.containsKey( c.getName() ) )
initBeanConfig( c );
return beanConfigs.get( c.getName() );
@ -81,13 +82,14 @@ class DBBeanConfig{
for( Field field : fields ){
int mod = field.getModifiers();
if( !Modifier.isTransient( mod ) &&
!Modifier.isAbstract( mod ) &&
!Modifier.isFinal( mod ) &&
!Modifier.isStatic( mod ) &&
!Modifier.isInterface( mod ) &&
!Modifier.isNative( mod ) &&
!config.fields.contains( field )){
config.fields.add( field );
if (List.class.isAssignableFrom(field.getType()) &&
field.getAnnotation(DBBean.DBLinkTable.class) != null)
config.subBeanFields.add( field );
else
config.fields.add( field );
}
}
if( tableAnn == null || !tableAnn.superBean() )
@ -97,10 +99,11 @@ class DBBeanConfig{
beanConfigs.put(c.getName(), config);
}
protected static String getFieldName(Field field){
public static String getFieldName(Field field){
DBBean.DBColumn colAnnotation = field.getAnnotation(DBBean.DBColumn.class);
if(colAnnotation != null)
return colAnnotation.value();
return field.getName();
}
}

View file

@ -171,40 +171,19 @@ public class DBBeanSQLResultHandler<T> implements SQLResultHandler<T>{
protected void updateBean(ResultSet result, DBBean obj) throws SQLException{
if (obj.readLock.tryLock()) {
try {
logger.fine("Updating Bean(" + beanClass.getName() + ") with id: " + obj.getId());
// Get the rest
logger.fine("Updating Bean("+ beanClass.getName() +") with id: "+ obj.getId());
// Read fields
for (Field field : beanConfig.fields) {
String name = DBBeanConfig.getFieldName(field);
// Another DBBean class
// Inline DBBean class
if (DBBean.class.isAssignableFrom(field.getType())) {
if (db != null) {
Long subid = result.getLong(name);
DBBean subobj = DBBeanCache.get(field.getType(), subid);
if (subobj == null)
subobj = DBBean.load(db, (Class<? extends DBBean>) field.getType(), subid);
obj.setFieldValue(field, subobj);
} else
logger.warning("No DB available to read sub beans");
}
// A list of DBBeans
else if (List.class.isAssignableFrom(field.getType()) &&
field.getAnnotation(DBLinkTable.class) != null) {
if (db != null) {
DBLinkTable linkTable = field.getAnnotation(DBLinkTable.class);
DBBeanConfig subConfig = DBBeanConfig.getBeanConfig(linkTable.beanClass());
String linkTableName = linkTable.table();
String subTable = subConfig.tableName;
String idcol = (linkTable.idColumn().isEmpty() ? beanConfig.tableName : linkTable.idColumn());
// Load list from link table
String subsql = "SELECT subObjTable.* FROM " + linkTableName + " as linkTable, " + subTable + " as subObjTable WHERE linkTable." + idcol + "=? AND linkTable." + subConfig.idColumn + "=subObjTable." + subConfig.idColumn;
logger.finest("List Load Query: " + subsql);
PreparedStatement subStmt = db.getPreparedStatement(subsql);
subStmt.setObject(1, obj.getId());
List<? extends DBBean> list = DBConnection.exec(subStmt,
DBBeanSQLResultHandler.createList(linkTable.beanClass(), db));
obj.setFieldValue(field, list);
Long subId = result.getLong(name);
DBBean subObj = DBBeanCache.get(field.getType(), subId);
if (subObj == null)
subObj = DBBean.load(db, (Class<? extends DBBean>) field.getType(), subId);
obj.setFieldValue(field, subObj);
} else
logger.warning("No DB available to read sub beans");
}
@ -213,7 +192,28 @@ public class DBBeanSQLResultHandler<T> implements SQLResultHandler<T>{
obj.setFieldValue(field, result.getObject(name));
}
}
// Read sub beans
if (db != null) {
for (Field field : beanConfig.subBeanFields) {
DBLinkTable linkTable = field.getAnnotation(DBLinkTable.class);
DBBeanConfig subConfig = DBBeanConfig.getBeanConfig(linkTable.beanClass());
String linkTableName = linkTable.table();
String subTable = subConfig.tableName;
String idCol = (linkTable.idColumn().isEmpty() ? beanConfig.tableName : linkTable.idColumn());
// Load list from link table
String subSql = "SELECT subObjTable.* FROM "+ linkTableName +" as linkTable, "+ subTable +" as subObjTable WHERE linkTable."+idCol+"=? AND linkTable."+subConfig.idColumn+"=subObjTable."+subConfig.idColumn;
logger.finest("List Load Query: " + subSql);
PreparedStatement subStmt = db.getPreparedStatement(subSql);
subStmt.setObject(1, obj.getId());
List<? extends DBBean> list = DBConnection.exec(subStmt,
DBBeanSQLResultHandler.createList(linkTable.beanClass(), db));
obj.setFieldValue(field, list);
}
} else
logger.warning("No DB available to read sub beans");
// Call post listener
obj.postUpdateAction();
} finally {
obj.readLock.unlock();