More Refactoring and added delete TC
This commit is contained in:
parent
5b15515432
commit
f9dc882c1c
6 changed files with 456 additions and 263 deletions
|
|
@ -25,23 +25,21 @@
|
|||
package zutil.db.bean;
|
||||
|
||||
import zutil.db.DBConnection;
|
||||
import zutil.db.bean.DBBeanConfig.DBBeanFieldConfig;
|
||||
import zutil.db.bean.DBBeanConfig.DBBeanSubBeanConfig;
|
||||
import zutil.log.LogUtil;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Timestamp;
|
||||
import java.util.List;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
|
|
@ -102,7 +100,7 @@ public abstract class DBBean {
|
|||
String table();
|
||||
/** The class of the linked bean */
|
||||
Class<? extends DBBean> beanClass();
|
||||
/** The name of the column that contains the main objects id, SQL rules apply, should not contain any strange characters or spaces */
|
||||
/** The name of the column that contains the parent beans id, SQL rules apply, should not contain any strange characters or spaces */
|
||||
String idColumn() default "";
|
||||
}
|
||||
|
||||
|
|
@ -126,7 +124,7 @@ public abstract class DBBean {
|
|||
|
||||
|
||||
/**
|
||||
* Saves the object and all the sub objects to the DB
|
||||
* Saves the bean and all its sub beans to the DB
|
||||
*
|
||||
* @param db is the DBMS connection
|
||||
*/
|
||||
|
|
@ -135,10 +133,10 @@ public abstract class DBBean {
|
|||
}
|
||||
|
||||
/**
|
||||
* Saves the Object to the DB
|
||||
* Saves the bean to the DB
|
||||
*
|
||||
* @param db is the DBMS connection
|
||||
* @param recursive is if all sub object also should be saved
|
||||
* @param db the DBMS connection
|
||||
* @param recursive if all sub beans should be saved also
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public void save(DBConnection db, boolean recursive) throws SQLException{
|
||||
|
|
@ -151,35 +149,35 @@ public abstract class DBBean {
|
|||
// Generate the SQL
|
||||
StringBuilder query = new StringBuilder();
|
||||
if (this.id == null) {
|
||||
query.append("INSERT INTO ").append(config.tableName);
|
||||
query.append("INSERT INTO ").append(config.getTableName());
|
||||
StringBuilder sqlCols = new StringBuilder();
|
||||
StringBuilder sqlValues = new StringBuilder();
|
||||
for (Field field : config.fields) {
|
||||
for (DBBeanFieldConfig field : config.getFields()) {
|
||||
if (sqlCols.length() > 0)
|
||||
sqlCols.append(", ");
|
||||
sqlCols.append(DBBeanConfig.getFieldName(field));
|
||||
sqlCols.append(field.getName());
|
||||
|
||||
if (sqlValues.length() > 0)
|
||||
sqlValues.append(", ");
|
||||
sqlValues.append("?");
|
||||
}
|
||||
if (config.fields.size() > 0) { // is there any fields?
|
||||
if (config.getFields().size() > 0) { // is there any fields?
|
||||
query.append(" (").append(sqlCols).append(")");
|
||||
query.append(" VALUES(").append(sqlValues).append(")");
|
||||
} else
|
||||
query.append(" DEFAULT VALUES");
|
||||
}
|
||||
else if (config.fields.size() > 0) { // Is there any fields to update?
|
||||
query.append("UPDATE ").append(config.tableName);
|
||||
else if (config.getFields().size() > 0) { // Is there any fields to update?
|
||||
query.append("UPDATE ").append(config.getTableName());
|
||||
StringBuilder sqlSets = new StringBuilder();
|
||||
for (Field field : config.fields) {
|
||||
for (DBBeanFieldConfig field : config.getFields()) {
|
||||
if (sqlSets.length() > 0)
|
||||
sqlSets.append(", ");
|
||||
sqlSets.append(DBBeanConfig.getFieldName(field));
|
||||
sqlSets.append(field.getName());
|
||||
sqlSets.append("=?");
|
||||
}
|
||||
query.append(" SET ").append(sqlSets);
|
||||
query.append(" WHERE ").append(config.idColumn).append("=?");
|
||||
query.append(" WHERE ").append(config.getIdColumnName()).append("=?");
|
||||
}
|
||||
|
||||
// Check if we have a valid query to run, skip otherwise
|
||||
|
|
@ -189,10 +187,10 @@ public abstract class DBBean {
|
|||
PreparedStatement stmt = db.getPreparedStatement(sql);
|
||||
// Put in the variables in the SQL
|
||||
int index = 1;
|
||||
for (Field field : config.fields) {
|
||||
for (DBBeanFieldConfig field : config.getFields()) {
|
||||
// Another DBBean class
|
||||
if (DBBean.class.isAssignableFrom(field.getType())) {
|
||||
DBBean subObj = (DBBean) getFieldValue(field);
|
||||
DBBean subObj = (DBBean) field.getValue(this);
|
||||
if (subObj != null) {
|
||||
if (recursive || subObj.getId() == null)
|
||||
subObj.save(db);
|
||||
|
|
@ -203,7 +201,7 @@ public abstract class DBBean {
|
|||
}
|
||||
// Normal field
|
||||
else {
|
||||
Object value = getFieldValue(field);
|
||||
Object value = field.getValue(this);
|
||||
stmt.setObject(index, value);
|
||||
index++;
|
||||
}
|
||||
|
|
@ -213,58 +211,50 @@ public abstract class DBBean {
|
|||
|
||||
// Execute the SQL
|
||||
DBConnection.exec(stmt);
|
||||
if (this.id == null) {
|
||||
if (this.id == null)
|
||||
this.id = db.getLastInsertID(stmt);
|
||||
// Add this bean to the cache
|
||||
DBBeanCache.add(this);
|
||||
}
|
||||
}
|
||||
// Update cache
|
||||
DBBeanCache.add(this);
|
||||
|
||||
// Save sub beans, after we get the parent object id
|
||||
for (Field field : config.subBeanFields) {
|
||||
if (this.id == null)
|
||||
throw new SQLException("Unknown parent object id");
|
||||
// Save sub beans, after we get the parent beans id
|
||||
if (recursive){
|
||||
for (DBBeanSubBeanConfig subBeanField : config.getSubBeans()) {
|
||||
if (this.id == null)
|
||||
throw new SQLException("Unknown parent bean 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>) subBeanField.getValue(this);
|
||||
if (list != null) {
|
||||
for (DBBean subObj : list) {
|
||||
// Save the sub bean
|
||||
subObj.save(db);
|
||||
if (subObj.getId() == null) {
|
||||
logger.severe("Unable to save field " + c.getSimpleName() + "." + subBeanField.getName() +
|
||||
" with " + subObj.getClass().getSimpleName() + " because sub bean id is null");
|
||||
continue;
|
||||
}
|
||||
// Get the Sub bean configuration
|
||||
String subIdCol = subBeanField.getSubBeanConfig().getIdColumnName();
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
// Save links in link table
|
||||
String sql;
|
||||
if (!subBeanField.isStandaloneLinkTable()) // Sub Bean and link table is the same table
|
||||
sql = "UPDATE "+ subBeanField.getLinkTableName() +" SET "+ subBeanField.getParentIdColumnName() +"=? WHERE "+ subIdCol +"=?";
|
||||
else
|
||||
sql = "INSERT INTO " + subBeanField.getLinkTableName() + " (" + subBeanField.getParentIdColumnName() + ", " + subIdCol + ") SELECT ?,? " +
|
||||
"WHERE NOT EXISTS(SELECT 1 FROM " + subBeanField.getLinkTableName() + " WHERE " + subBeanField.getParentIdColumnName() + "=? 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;
|
||||
|
|
@ -280,25 +270,53 @@ public abstract class DBBean {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Deletes the bean from the DB and all its sub beans and links.
|
||||
*/
|
||||
public void delete(DBConnection db) throws SQLException{
|
||||
delete(db, true);
|
||||
}
|
||||
/**
|
||||
* Deletes the object from the DB, WARNING will not delete sub beans
|
||||
*
|
||||
* @throws SQLException
|
||||
* Deletes the bean from the DB and the links to sub beans.
|
||||
*
|
||||
* @param recursive if all sub beans should be deleted also
|
||||
*/
|
||||
public void delete(DBConnection db) throws SQLException{
|
||||
public void delete(DBConnection db, boolean recursive) throws SQLException{
|
||||
Class<? extends DBBean> c = this.getClass();
|
||||
DBBeanConfig config = DBBeanConfig.getBeanConfig( c );
|
||||
if( this.getId() == null )
|
||||
throw new NullPointerException("ID field is null! (Has the bean been saved?)");
|
||||
|
||||
String sql = "DELETE FROM "+config.tableName+" WHERE "+config.idColumn+"=?";
|
||||
// Delete sub beans
|
||||
for (DBBeanSubBeanConfig subBeanField : config.getSubBeans()) {
|
||||
List<DBBean> list = (List<DBBean>) subBeanField.getValue(this);
|
||||
if (list != null) {
|
||||
for (DBBean subObj : list) {
|
||||
// Delete links
|
||||
if (subBeanField.isStandaloneLinkTable()) {
|
||||
String sql = "DELETE FROM "+subBeanField.getLinkTableName()+" WHERE "+subBeanField.getParentIdColumnName()+"=?";
|
||||
logger.finest("Delete link, query: "+sql);
|
||||
PreparedStatement stmt = db.getPreparedStatement( sql );
|
||||
stmt.setLong(1, this.getId() );
|
||||
DBConnection.exec(stmt);
|
||||
}
|
||||
// Delete sub beans
|
||||
if (recursive)
|
||||
subObj.delete(db);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Delete this bean from DB
|
||||
String sql = "DELETE FROM "+config.getTableName()+" WHERE "+config.getIdColumnName()+"=?";
|
||||
logger.finest("Delete Bean("+c.getName()+", id: "+this.getId()+") query: "+sql);
|
||||
PreparedStatement stmt = db.getPreparedStatement( sql );
|
||||
// Put in the variables in the SQL
|
||||
stmt.setObject(1, this.getId() );
|
||||
|
||||
// Execute the SQL
|
||||
stmt.setLong(1, this.getId() );
|
||||
DBConnection.exec(stmt);
|
||||
|
||||
// Clear cache and reset id
|
||||
DBBeanCache.remove(this);
|
||||
this.id = null;
|
||||
}
|
||||
|
||||
|
|
@ -313,7 +331,7 @@ public abstract class DBBean {
|
|||
// Initiate a BeanConfig if there is non
|
||||
DBBeanConfig config = DBBeanConfig.getBeanConfig( c );
|
||||
// Generate query
|
||||
String sql = "SELECT * FROM "+config.tableName;
|
||||
String sql = "SELECT * FROM "+config.getTableName();
|
||||
logger.finest("Load all Beans("+c.getName()+") query: "+sql);
|
||||
PreparedStatement stmt = db.getPreparedStatement( sql );
|
||||
// Run query
|
||||
|
|
@ -333,7 +351,7 @@ public abstract class DBBean {
|
|||
// Initiate a BeanConfig if there is non
|
||||
DBBeanConfig config = DBBeanConfig.getBeanConfig( c );
|
||||
// Generate query
|
||||
String sql = "SELECT * FROM "+config.tableName+" WHERE "+config.idColumn+"=? LIMIT 1";
|
||||
String sql = "SELECT * FROM "+config.getTableName()+" WHERE "+config.getIdColumnName()+"=? LIMIT 1";
|
||||
logger.finest("Load Bean("+c.getName()+", id: "+id+") query: "+sql);
|
||||
PreparedStatement stmt = db.getPreparedStatement( sql );
|
||||
stmt.setObject(1, id );
|
||||
|
|
@ -351,20 +369,20 @@ public abstract class DBBean {
|
|||
|
||||
// Generate the SQL
|
||||
StringBuilder query = new StringBuilder();
|
||||
query.append("CREATE TABLE "+config.tableName+" ( ");
|
||||
query.append("CREATE TABLE "+config.getTableName()+" ( ");
|
||||
|
||||
// ID
|
||||
query.append(" ").append(config.idColumn).append(" ");
|
||||
query.append( classToColType( Long.class ) );
|
||||
query.append(" ").append(config.getIdColumnName()).append(" ");
|
||||
query.append( classToDBType( Long.class ) );
|
||||
query.append(" PRIMARY KEY AUTO_INCREMENT, ");
|
||||
|
||||
for( Field field : config.fields ){
|
||||
for( DBBeanFieldConfig field : config.getFields() ){
|
||||
query.append(" ");
|
||||
query.append( DBBeanConfig.getFieldName(field) );
|
||||
query.append( classToColType(c) );
|
||||
query.append(field.getName());
|
||||
query.append(classToDBType(c));
|
||||
query.append(", ");
|
||||
}
|
||||
query.delete( query.length()-2, query.length());
|
||||
query.delete(query.length()-2, query.length());
|
||||
query.append(")");
|
||||
|
||||
logger.finest("Create Bean("+c.getName()+") query: "+sql.toString());
|
||||
|
|
@ -374,7 +392,7 @@ public abstract class DBBean {
|
|||
DBConnection.exec(stmt);
|
||||
}
|
||||
|
||||
private static String classToColType(Class<?> c){
|
||||
private static String classToDBType(Class<?> c){
|
||||
if( c == String.class) return "CLOB"; // TEXT
|
||||
else if(c == Short.class) return "SMALLINT";
|
||||
else if(c == short.class) return "SMALLINT";
|
||||
|
|
@ -394,64 +412,12 @@ public abstract class DBBean {
|
|||
else if(c == byte.class) return "BINARY(1)";
|
||||
else if(c == Timestamp.class) return "DATETIME";
|
||||
else if(DBBean.class.isAssignableFrom(c))
|
||||
return classToColType(Long.class);
|
||||
return classToDBType(Long.class);
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a workaround if the field is not visible to other classes
|
||||
*
|
||||
* @param field is the field
|
||||
* @return the value of the field
|
||||
*/
|
||||
protected Object getFieldValue(Field field){
|
||||
try {
|
||||
if( !Modifier.isPublic( field.getModifiers()))
|
||||
field.setAccessible(true);
|
||||
|
||||
return field.get(this);
|
||||
} catch (Exception e) {
|
||||
logger.log(Level.WARNING, e.getMessage(), e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a workaround if the field is not visible to other classes
|
||||
*
|
||||
* @param field is the field
|
||||
* @return the value of the field
|
||||
*/
|
||||
protected void setFieldValue(Field field, Object o){
|
||||
try {
|
||||
if( !Modifier.isPublic( field.getModifiers()))
|
||||
field.setAccessible(true);
|
||||
|
||||
// Set basic data type
|
||||
if( o == null && !Object.class.isAssignableFrom( field.getType() ) ){
|
||||
if( field.getType() == Integer.TYPE ) field.setInt(this, 0);
|
||||
else if( field.getType() == Character.TYPE )field.setChar(this, (char) 0);
|
||||
else if( field.getType() == Byte.TYPE ) field.setByte(this, (byte) 0);
|
||||
else if( field.getType() == Short.TYPE ) field.setShort(this, (short) 0);
|
||||
else if( field.getType() == Long.TYPE ) field.setLong(this, 0l);
|
||||
else if( field.getType() == Float.TYPE ) field.setFloat(this, 0f);
|
||||
else if( field.getType() == Double.TYPE ) field.setDouble(this, 0d);
|
||||
else if( field.getType() == Boolean.TYPE ) field.setBoolean(this, false);
|
||||
}
|
||||
else {
|
||||
// Some special cases
|
||||
if(field.getType() == Boolean.TYPE && o instanceof Integer)
|
||||
field.setBoolean(this, ((Integer)o) > 0 ); // Convert an Integer to boolean
|
||||
else
|
||||
field.set(this, o);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.log(Level.SEVERE, e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the object id or null if the bean has not bean saved yet
|
||||
* @return the bean id or null if the bean has not bean saved yet
|
||||
*/
|
||||
public final Long getId(){
|
||||
return id;
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ class DBBeanCache {
|
|||
}
|
||||
|
||||
/**
|
||||
* A cache container that contains a object and last read time
|
||||
* A cache container that contains a bean and its last filed update time
|
||||
*/
|
||||
private static class CacheItem{
|
||||
public long updateTimestamp;
|
||||
|
|
@ -113,41 +113,16 @@ class DBBeanCache {
|
|||
}
|
||||
|
||||
/**
|
||||
* Will check the cache if the given object exists
|
||||
* Will check the cache if the given bean exists
|
||||
*
|
||||
* @param c is the class of the bean
|
||||
* @param id is the id of the bean
|
||||
* @return a cached DBBean object, or null if there is no cached object or if the cache is to old
|
||||
* @return a cached DBBean object, null if there is a cache miss
|
||||
*/
|
||||
public static DBBean get(Class<?> c, Long id){
|
||||
try{
|
||||
return get( c, id, null );
|
||||
}catch(SQLException e){
|
||||
throw new RuntimeException("This exception should not be thrown, Something went really wrong!", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Will check the cache if the given object exists and will update it if its old
|
||||
*
|
||||
* @param c is the class of the bean
|
||||
* @param id is the id of the bean
|
||||
* @param result is the ResultSet for this object, the object will be updated from this ResultSet if the object is to old, there will be no update if this parameter is null
|
||||
* @return a cached DBBean object, might update the cached object if its old but only if the ResultSet parameter is set
|
||||
*/
|
||||
public static DBBean get(Class<?> c, Long id, ResultSet result) throws SQLException{
|
||||
public static DBBean get(Class<?> c, Long id) {
|
||||
if(contains(c, id)){
|
||||
CacheItem cacheItem = cache.get(c).get(id);
|
||||
DBBean bean = cacheItem.bean.get();
|
||||
// The cache is old, update and return it
|
||||
if (cacheItem.updateTimestamp + CACHE_DATA_TTL < System.currentTimeMillis()) {
|
||||
// There is no ResultSet to update from
|
||||
if (result == null)
|
||||
return null;
|
||||
// Only update object if there is no update running now
|
||||
logger.finer("Bean(" + c.getName() + ") cache to old for id: " + id);
|
||||
// TODO:updateBean(result, bean);
|
||||
}
|
||||
return bean;
|
||||
}
|
||||
logger.finer("Bean("+c.getName()+") cache miss for id: "+id);
|
||||
|
|
@ -155,14 +130,25 @@ class DBBeanCache {
|
|||
}
|
||||
|
||||
/**
|
||||
* Will check if the object with the id already exists in the cahce,
|
||||
* if not then it will add the given object to the cache.
|
||||
*
|
||||
* @param obj is the object to cache
|
||||
* @return true if the bean data is outdated, false if the data is current or if the bean was not found in the cache
|
||||
*/
|
||||
public static boolean isOutDated(DBBean obj){
|
||||
if(contains(obj)) {
|
||||
CacheItem cacheItem = cache.get(obj.getClass()).get(obj.getId());
|
||||
return cacheItem.updateTimestamp + CACHE_DATA_TTL < System.currentTimeMillis();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Will add a bean to the cache. If the bean already is in
|
||||
* the cache then its TTL timer will be reset
|
||||
*/
|
||||
public synchronized static void add(DBBean obj) {
|
||||
if (contains(obj))
|
||||
if (contains(obj)) {
|
||||
cache.get(obj.getClass()).get(obj.getId()).updateTimestamp = System.currentTimeMillis();
|
||||
return;
|
||||
}
|
||||
CacheItem cacheItem = new CacheItem();
|
||||
cacheItem.updateTimestamp = System.currentTimeMillis();
|
||||
cacheItem.bean = new WeakReference<>(obj);
|
||||
|
|
@ -174,4 +160,10 @@ class DBBeanCache {
|
|||
cache.put(obj.getClass(), map);
|
||||
}
|
||||
}
|
||||
|
||||
public static void remove(DBBean obj){
|
||||
if (obj != null)
|
||||
if( cache.containsKey(obj.getClass()) )
|
||||
cache.get(obj.getClass()).remove(obj.getId());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,6 +24,8 @@
|
|||
|
||||
package zutil.db.bean;
|
||||
|
||||
import zutil.ClassUtil;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
|
|
@ -39,13 +41,13 @@ class DBBeanConfig{
|
|||
|
||||
|
||||
/** The name of the table in the DB **/
|
||||
public String tableName;
|
||||
private String tableName;
|
||||
/** The name of the id column **/
|
||||
public String idColumn;
|
||||
private String idColumnName;
|
||||
/** All normal fields in the bean **/
|
||||
public ArrayList<Field> fields = new ArrayList<>();
|
||||
private ArrayList<DBBeanFieldConfig> fields = new ArrayList<>();
|
||||
/** All sub bean fields in the bean **/
|
||||
public ArrayList<Field> subBeanFields = new ArrayList<>();
|
||||
private ArrayList<DBBeanSubBeanConfig> subBeanFields = new ArrayList<>();
|
||||
|
||||
|
||||
private DBBeanConfig(){ }
|
||||
|
|
@ -70,12 +72,12 @@ class DBBeanConfig{
|
|||
DBBean.DBTable tableAnn = c.getAnnotation(DBBean.DBTable.class);
|
||||
if( tableAnn != null ){
|
||||
config.tableName = tableAnn.value();
|
||||
config.idColumn = tableAnn.idColumn();
|
||||
}
|
||||
else{
|
||||
config.idColumnName = tableAnn.idColumn();
|
||||
} else {
|
||||
config.tableName = c.getSimpleName();
|
||||
config.idColumn = "id";
|
||||
config.idColumnName = "id";
|
||||
}
|
||||
|
||||
// Add the fields in the bean and all the super classes fields
|
||||
for(Class<?> cc = c; cc != DBBean.class ;cc = cc.getSuperclass()){
|
||||
Field[] fields = cc.getDeclaredFields();
|
||||
|
|
@ -87,9 +89,9 @@ class DBBeanConfig{
|
|||
!config.fields.contains( field )){
|
||||
if (List.class.isAssignableFrom(field.getType()) &&
|
||||
field.getAnnotation(DBBean.DBLinkTable.class) != null)
|
||||
config.subBeanFields.add( field );
|
||||
config.subBeanFields.add(new DBBeanSubBeanConfig(field));
|
||||
else
|
||||
config.fields.add( field );
|
||||
config.fields.add(new DBBeanFieldConfig(field));
|
||||
}
|
||||
}
|
||||
if( tableAnn == null || !tableAnn.superBean() )
|
||||
|
|
@ -99,11 +101,122 @@ class DBBeanConfig{
|
|||
beanConfigs.put(c.getName(), config);
|
||||
}
|
||||
|
||||
public static String getFieldName(Field field){
|
||||
DBBean.DBColumn colAnnotation = field.getAnnotation(DBBean.DBColumn.class);
|
||||
if(colAnnotation != null)
|
||||
return colAnnotation.value();
|
||||
return field.getName();
|
||||
|
||||
public String getTableName(){
|
||||
return tableName;
|
||||
}
|
||||
|
||||
public String getIdColumnName(){
|
||||
return idColumnName;
|
||||
}
|
||||
|
||||
public List<DBBeanFieldConfig> getFields(){
|
||||
return fields;
|
||||
}
|
||||
|
||||
public List<DBBeanSubBeanConfig> getSubBeans(){
|
||||
return subBeanFields;
|
||||
}
|
||||
|
||||
|
||||
public static class DBBeanFieldConfig {
|
||||
private Field field;
|
||||
private String fieldName;
|
||||
|
||||
private DBBeanFieldConfig(Field field){
|
||||
this.field = field;
|
||||
if( !Modifier.isPublic( field.getModifiers()))
|
||||
field.setAccessible(true);
|
||||
|
||||
DBBean.DBColumn colAnnotation = field.getAnnotation(DBBean.DBColumn.class);
|
||||
if(colAnnotation != null)
|
||||
fieldName = colAnnotation.value();
|
||||
else
|
||||
fieldName = field.getName();
|
||||
}
|
||||
|
||||
|
||||
public String getName(){
|
||||
return fieldName;
|
||||
}
|
||||
|
||||
public Class<?> getType(){
|
||||
return field.getType();
|
||||
}
|
||||
|
||||
public Object getValue(Object obj) {
|
||||
try {
|
||||
return field.get(obj);
|
||||
} catch (Exception e){
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void setValue(Object obj, Object fieldValue) {
|
||||
try {
|
||||
if (!Modifier.isPublic(field.getModifiers()))
|
||||
field.setAccessible(true);
|
||||
|
||||
// Set basic data type
|
||||
if (fieldValue == null && ClassUtil.isPrimitive(field.getType())) {
|
||||
if (field.getType() == Integer.TYPE) field.setInt(obj, 0);
|
||||
else if (field.getType() == Character.TYPE) field.setChar(obj, (char) 0);
|
||||
else if (field.getType() == Byte.TYPE) field.setByte(obj, (byte) 0);
|
||||
else if (field.getType() == Short.TYPE) field.setShort(obj, (short) 0);
|
||||
else if (field.getType() == Long.TYPE) field.setLong(obj, 0l);
|
||||
else if (field.getType() == Float.TYPE) field.setFloat(obj, 0f);
|
||||
else if (field.getType() == Double.TYPE) field.setDouble(obj, 0d);
|
||||
else if (field.getType() == Boolean.TYPE) field.setBoolean(obj, false);
|
||||
} else {
|
||||
// Some special cases
|
||||
if (field.getType() == Boolean.TYPE && fieldValue instanceof Integer)
|
||||
field.setBoolean(obj, ((Integer) fieldValue) > 0); // Convert an Integer to boolean
|
||||
else
|
||||
field.set(obj, fieldValue);
|
||||
}
|
||||
} catch (Exception e){
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class DBBeanSubBeanConfig extends DBBeanFieldConfig{
|
||||
private String linkTableName;
|
||||
private Class<? extends DBBean> subBeanClass;
|
||||
private DBBeanConfig subBeanConfig;
|
||||
private String parentIdCol;
|
||||
|
||||
private DBBeanSubBeanConfig(Field field){
|
||||
super(field);
|
||||
|
||||
DBBean.DBLinkTable linkAnnotation = field.getAnnotation(DBBean.DBLinkTable.class);
|
||||
this.linkTableName = linkAnnotation.table();
|
||||
this.subBeanClass = linkAnnotation.beanClass();
|
||||
this.subBeanConfig = DBBeanConfig.getBeanConfig(subBeanClass);
|
||||
this.parentIdCol = linkAnnotation.idColumn();
|
||||
}
|
||||
|
||||
|
||||
public String getLinkTableName() {
|
||||
return linkTableName;
|
||||
}
|
||||
|
||||
public boolean isStandaloneLinkTable(){
|
||||
return !linkTableName.equals(subBeanConfig.tableName);
|
||||
}
|
||||
|
||||
public Class<? extends DBBean> getSubBeanClass() {
|
||||
return subBeanClass;
|
||||
}
|
||||
|
||||
public DBBeanConfig getSubBeanConfig() {
|
||||
return subBeanConfig;
|
||||
}
|
||||
|
||||
public String getParentIdColumnName() {
|
||||
return parentIdCol;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -26,10 +26,10 @@ package zutil.db.bean;
|
|||
|
||||
import zutil.db.DBConnection;
|
||||
import zutil.db.SQLResultHandler;
|
||||
import zutil.db.bean.DBBean.DBLinkTable;
|
||||
import zutil.db.bean.DBBeanConfig.DBBeanFieldConfig;
|
||||
import zutil.db.bean.DBBeanConfig.DBBeanSubBeanConfig;
|
||||
import zutil.log.LogUtil;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
|
|
@ -55,7 +55,7 @@ public class DBBeanSQLResultHandler<T> implements SQLResultHandler<T>{
|
|||
* @return a new instance of this class
|
||||
*/
|
||||
public static <C extends DBBean> DBBeanSQLResultHandler<C> create(Class<C> cl){
|
||||
return new DBBeanSQLResultHandler<C>(cl, null, false);
|
||||
return new DBBeanSQLResultHandler<>(cl, null, false);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -115,7 +115,7 @@ public class DBBeanSQLResultHandler<T> implements SQLResultHandler<T>{
|
|||
@SuppressWarnings("unchecked")
|
||||
public T handleQueryResult(Statement stmt, ResultSet result) throws SQLException{
|
||||
if( list ){
|
||||
LinkedList<DBBean> bean_list = new LinkedList<DBBean>();
|
||||
List<DBBean> bean_list = new LinkedList<>();
|
||||
while( result.next() ){
|
||||
DBBean obj = createBean(result);
|
||||
bean_list.add( obj );
|
||||
|
|
@ -138,21 +138,23 @@ public class DBBeanSQLResultHandler<T> implements SQLResultHandler<T>{
|
|||
* @param result is where the field values for the bean will bee read from, the cursor should be in front of the data
|
||||
* @return a new instance of the bean
|
||||
*/
|
||||
protected DBBean createBean(ResultSet result) throws SQLException{
|
||||
private DBBean createBean(ResultSet result) throws SQLException{
|
||||
try {
|
||||
Long id = result.getLong( "id" );
|
||||
// Check cache first
|
||||
DBBean obj = DBBeanCache.get(beanClass, id, result);
|
||||
DBBean obj = DBBeanCache.get(beanClass, id);
|
||||
if ( obj == null ) {
|
||||
// Cache miss create a new object
|
||||
// Cache miss create a new bean
|
||||
logger.fine("Creating new Bean(" + beanClass.getName() + ") with id: " + id);
|
||||
obj = beanClass.newInstance();
|
||||
obj.setId(id);
|
||||
DBBeanCache.add(obj);
|
||||
updateBean( result, obj );
|
||||
}
|
||||
else if (DBBeanCache.isOutDated(obj)){
|
||||
// Update fields
|
||||
logger.finer("Bean(" + beanClass.getName() + ") cache to old for id: " + id);
|
||||
updateBean(result, obj);
|
||||
}
|
||||
|
||||
// Update fields
|
||||
updateBean( result, obj );
|
||||
return obj;
|
||||
} catch (SQLException e) {
|
||||
throw e;
|
||||
|
|
@ -164,17 +166,17 @@ public class DBBeanSQLResultHandler<T> implements SQLResultHandler<T>{
|
|||
/**
|
||||
* Updates an existing bean and assigns field values from the ResultSet
|
||||
*
|
||||
* @param result is where the field values for the bean will bee read from, the cursor should be in front of the data
|
||||
* @param obj is the object that will be updated
|
||||
* @param result is where the field values for the bean will be read from, the cursor should be in front of the data
|
||||
* @param obj is the bean that will be updated
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
protected void updateBean(ResultSet result, DBBean obj) throws SQLException{
|
||||
private void updateBean(ResultSet result, DBBean obj) throws SQLException{
|
||||
if (obj.readLock.tryLock()) {
|
||||
try {
|
||||
logger.fine("Updating Bean("+ beanClass.getName() +") with id: "+ obj.getId());
|
||||
// Read fields
|
||||
for (Field field : beanConfig.fields) {
|
||||
String name = DBBeanConfig.getFieldName(field);
|
||||
for (DBBeanFieldConfig field : beanConfig.getFields()) {
|
||||
String name = field.getName();
|
||||
|
||||
// Inline DBBean class
|
||||
if (DBBean.class.isAssignableFrom(field.getType())) {
|
||||
|
|
@ -183,32 +185,35 @@ public class DBBeanSQLResultHandler<T> implements SQLResultHandler<T>{
|
|||
DBBean subObj = DBBeanCache.get(field.getType(), subId);
|
||||
if (subObj == null)
|
||||
subObj = DBBean.load(db, (Class<? extends DBBean>) field.getType(), subId);
|
||||
obj.setFieldValue(field, subObj);
|
||||
field.setValue(obj, subObj);
|
||||
} else
|
||||
logger.warning("No DB available to read sub beans");
|
||||
}
|
||||
// Normal field
|
||||
else {
|
||||
obj.setFieldValue(field, result.getObject(name));
|
||||
field.setValue(obj, result.getObject(name));
|
||||
}
|
||||
}
|
||||
// Update cache
|
||||
DBBeanCache.add(obj);
|
||||
|
||||
// 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());
|
||||
for (DBBeanSubBeanConfig subBeanField : beanConfig.getSubBeans()) {
|
||||
DBBeanConfig subBeanConfig = subBeanField.getSubBeanConfig();
|
||||
|
||||
// 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;
|
||||
// Load List from link table
|
||||
String subSql = "SELECT subBeanTable.* FROM "+
|
||||
subBeanField.getLinkTableName() +" as linkTable, "+
|
||||
subBeanConfig.getTableName() +" as subBeanTable " +
|
||||
"WHERE linkTable."+subBeanField.getParentIdColumnName()+"=? AND " +
|
||||
"linkTable."+subBeanConfig.getIdColumnName()+"=subBeanTable."+subBeanConfig.getIdColumnName();
|
||||
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);
|
||||
DBBeanSQLResultHandler.createList(subBeanField.getSubBeanClass(), db));
|
||||
subBeanField.setValue(obj, list);
|
||||
}
|
||||
} else
|
||||
logger.warning("No DB available to read sub beans");
|
||||
|
|
|
|||
117
test/zutil/db/bean/DBBeanDeleteTest.java
Executable file
117
test/zutil/db/bean/DBBeanDeleteTest.java
Executable file
|
|
@ -0,0 +1,117 @@
|
|||
package zutil.db.bean;
|
||||
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import zutil.db.DBConnection;
|
||||
import zutil.log.CompactLogFormatter;
|
||||
import zutil.log.LogUtil;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import static junit.framework.TestCase.assertNull;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static zutil.db.bean.DBBeanTestBase.*;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class DBBeanDeleteTest {
|
||||
|
||||
private DBConnection db = new DBConnection(DBConnection.DBMS.SQLite, ":memory:");
|
||||
public DBBeanDeleteTest() throws Exception {}
|
||||
|
||||
@BeforeClass
|
||||
public static void init(){
|
||||
LogUtil.setGlobalFormatter(new CompactLogFormatter());
|
||||
LogUtil.setGlobalLevel(Level.ALL);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Test
|
||||
public void simpleClassDelete() throws SQLException {
|
||||
SimpleTestClass obj = simpleClassInit(db);
|
||||
obj.save(db);
|
||||
obj.delete(db);
|
||||
|
||||
assertEquals(0, DBBeanTestBase.getRowCount(db, "SimpleTestClass"));
|
||||
assertNull(obj.getId());
|
||||
assertNull(DBBeanCache.get(SimpleTestClass.class, 1L));
|
||||
}
|
||||
|
||||
@Test(expected=NullPointerException.class)
|
||||
public void notSavedSimpleClassDelete() throws SQLException {
|
||||
simpleClassInit(db).save(db);
|
||||
SimpleTestClass obj = new SimpleTestClass();
|
||||
obj.delete(db); // Exception
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multiSimpleClassDelete() throws SQLException {
|
||||
SimpleTestClass obj = simpleClassInit(db);
|
||||
obj.save(db);
|
||||
for(int i=0; i<5; ++i)
|
||||
new SimpleTestClass().save(db);
|
||||
obj.delete(db);
|
||||
|
||||
assertEquals(5, DBBeanTestBase.getRowCount(db, "SimpleTestClass"));
|
||||
assertNull(obj.getId());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Test
|
||||
public void emptySubObjectDelete() throws SQLException {
|
||||
subObjectInit(db).save(db);
|
||||
ParentTestClass obj = new ParentTestClass();
|
||||
obj.save(db);
|
||||
obj.delete(db);
|
||||
|
||||
assertEquals(1, DBBeanTestBase.getRowCount(db, "parent"));
|
||||
assertEquals(1, DBBeanTestBase.getRowCount(db, "subobject"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void subObjectDelete() throws SQLException {
|
||||
ParentTestClass obj = subObjectInit(db);
|
||||
obj.save(db);
|
||||
obj.delete(db);
|
||||
|
||||
assertEquals("Parent table size", 0, DBBeanTestBase.getRowCount(db, "parent"));
|
||||
assertEquals("SubObject table size", 0, DBBeanTestBase.getRowCount(db, "subobject"));
|
||||
assertNull(DBBeanCache.get(ParentTestClass.class, 1L));
|
||||
assertNull(DBBeanCache.get(SubObjectTestClass.class, 1L));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Test
|
||||
public void emptySubLinkObjectDelete() throws SQLException {
|
||||
subLinkObjectInit(db).save(db);
|
||||
ParentLinkTestClass obj = new ParentLinkTestClass();
|
||||
obj.save(db);
|
||||
obj.delete(db);
|
||||
|
||||
assertEquals("Parent table size", 1, DBBeanTestBase.getRowCount(db, "parent"));
|
||||
assertEquals("Link table size", 1, DBBeanTestBase.getRowCount(db, "link"));
|
||||
assertEquals("SubObject table size", 1, DBBeanTestBase.getRowCount(db, "subobject"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void subLinkObjectDelete() throws SQLException {
|
||||
ParentLinkTestClass obj = subLinkObjectInit(db);
|
||||
obj.save(db);
|
||||
obj.delete(db);
|
||||
|
||||
assertEquals("Parent table size", 0, DBBeanTestBase.getRowCount(db, "parent"));
|
||||
assertEquals("Link table size", 0, DBBeanTestBase.getRowCount(db, "link"));
|
||||
assertEquals("SubObject table size", 0, DBBeanTestBase.getRowCount(db, "subobject"));
|
||||
assertNull(DBBeanCache.get(ParentTestClass.class, 1L));
|
||||
assertNull(DBBeanCache.get(SubObjectTestClass.class, 1L));
|
||||
}
|
||||
}
|
||||
|
|
@ -33,10 +33,10 @@ public class DBBeanLoadTest {
|
|||
@Test
|
||||
public void simpleClassLoad() throws SQLException {
|
||||
simpleClassInit(db);
|
||||
insert(db, "SimpleTestClass", "5", "1234", "\"helloworld\"");
|
||||
SimpleTestClass obj = DBBean.load(db, SimpleTestClass.class, 5);
|
||||
insert(db, "SimpleTestClass", "10", "1234", "\"helloworld\"");
|
||||
SimpleTestClass obj = DBBean.load(db, SimpleTestClass.class, 10);
|
||||
|
||||
assertEquals((Long)5L, obj.getId());
|
||||
assertEquals((Long)10L, obj.getId());
|
||||
assertEquals(1234, obj.intField);
|
||||
assertEquals("helloworld", obj.strField);
|
||||
}
|
||||
|
|
@ -45,9 +45,9 @@ public class DBBeanLoadTest {
|
|||
@Test
|
||||
public void simpleClassCache() throws SQLException {
|
||||
simpleClassInit(db);
|
||||
insert(db, "SimpleTestClass", "5", "1234", "\"helloworld\"");
|
||||
SimpleTestClass obj1 = DBBean.load(db, SimpleTestClass.class, 5);
|
||||
SimpleTestClass obj2 = DBBean.load(db, SimpleTestClass.class, 5);
|
||||
insert(db, "SimpleTestClass", "11", "1234", "\"helloworld\"");
|
||||
SimpleTestClass obj1 = DBBean.load(db, SimpleTestClass.class, 11);
|
||||
SimpleTestClass obj2 = DBBean.load(db, SimpleTestClass.class, 11);
|
||||
|
||||
assertSame(obj1, obj2);
|
||||
}
|
||||
|
|
@ -58,10 +58,10 @@ public class DBBeanLoadTest {
|
|||
@Test
|
||||
public void aliasFieldsLoad() throws SQLException {
|
||||
aliasFieldsInit(db);
|
||||
insert(db, "aliasTable", "5", "1234", "\"helloworld\"");
|
||||
AliasFieldsTestClass obj = DBBean.load(db, AliasFieldsTestClass.class, 5);
|
||||
insert(db, "aliasTable", "20", "1234", "\"helloworld\"");
|
||||
AliasFieldsTestClass obj = DBBean.load(db, AliasFieldsTestClass.class, 20);
|
||||
|
||||
assertEquals((Long)5L, obj.getId());
|
||||
assertEquals((Long)20L, obj.getId());
|
||||
assertEquals(1234, obj.intField);
|
||||
assertEquals("helloworld", obj.strField);
|
||||
}
|
||||
|
|
@ -72,43 +72,43 @@ public class DBBeanLoadTest {
|
|||
@Test
|
||||
public void emptySubObjectLoad() throws SQLException {
|
||||
subObjectInit(db);
|
||||
insert(db, "parent", "5");
|
||||
ParentTestClass obj = DBBean.load(db, ParentTestClass.class, 5);
|
||||
insert(db, "parent", "30");
|
||||
ParentTestClass obj = DBBean.load(db, ParentTestClass.class, 30);
|
||||
|
||||
assertEquals((Long)5L, obj.getId());
|
||||
assertEquals((Long)30L, obj.getId());
|
||||
assertEquals(0, obj.subobjs.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void subObjectLoad() throws SQLException {
|
||||
subObjectInit(db);
|
||||
insert(db, "parent", "5");
|
||||
insert(db, "subobject", "10", "5", "1234");
|
||||
ParentTestClass obj = DBBean.load(db, ParentTestClass.class, 5);
|
||||
insert(db, "parent", "31");
|
||||
insert(db, "subobject", "310", "31", "1234");
|
||||
ParentTestClass obj = DBBean.load(db, ParentTestClass.class, 31);
|
||||
|
||||
assertEquals(1, obj.subobjs.size());
|
||||
assertEquals((Long)10L, obj.subobjs.get(0).getId());
|
||||
assertEquals((Long)310L, obj.subobjs.get(0).getId());
|
||||
assertEquals(1234, obj.subobjs.get(0).intField);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multiSubObjectLoad() throws SQLException {
|
||||
subObjectInit(db);
|
||||
insert(db, "parent", "5");
|
||||
insert(db, "subobject", "10", "5", "1001");
|
||||
insert(db, "subobject", "11", "5", "1002");
|
||||
insert(db, "subobject", "12", "5", "1003");
|
||||
insert(db, "subobject", "13", "5", "1004");
|
||||
ParentTestClass obj = DBBean.load(db, ParentTestClass.class, 5);
|
||||
insert(db, "parent", "32");
|
||||
insert(db, "subobject", "320", "32", "1001");
|
||||
insert(db, "subobject", "321", "32", "1002");
|
||||
insert(db, "subobject", "322", "32", "1003");
|
||||
insert(db, "subobject", "323", "32", "1004");
|
||||
ParentTestClass obj = DBBean.load(db, ParentTestClass.class, 32);
|
||||
|
||||
assertEquals(4, obj.subobjs.size());
|
||||
assertEquals((Long)10L, obj.subobjs.get(0).getId());
|
||||
assertEquals((Long)320L, obj.subobjs.get(0).getId());
|
||||
assertEquals(1001, obj.subobjs.get(0).intField);
|
||||
assertEquals((Long)11L, obj.subobjs.get(1).getId());
|
||||
assertEquals((Long)321L, obj.subobjs.get(1).getId());
|
||||
assertEquals(1002, obj.subobjs.get(1).intField);
|
||||
assertEquals((Long)12L, obj.subobjs.get(2).getId());
|
||||
assertEquals((Long)322L, obj.subobjs.get(2).getId());
|
||||
assertEquals(1003, obj.subobjs.get(2).intField);
|
||||
assertEquals((Long)13L, obj.subobjs.get(3).getId());
|
||||
assertEquals((Long)323L, obj.subobjs.get(3).getId());
|
||||
assertEquals(1004, obj.subobjs.get(3).intField);
|
||||
}
|
||||
|
||||
|
|
@ -118,44 +118,44 @@ public class DBBeanLoadTest {
|
|||
@Test
|
||||
public void emptySubLinkObjectLoad() throws SQLException {
|
||||
subLinkObjectInit(db);
|
||||
insert(db, "parent", "5");
|
||||
ParentLinkTestClass obj = DBBean.load(db, ParentLinkTestClass.class, 5);
|
||||
insert(db, "parent", "40");
|
||||
ParentLinkTestClass obj = DBBean.load(db, ParentLinkTestClass.class, 40);
|
||||
|
||||
assertEquals((Long)5L, obj.getId());
|
||||
assertEquals((Long)40L, obj.getId());
|
||||
assertEquals(0, obj.subobjs.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void subLinkObjectLoad() throws SQLException {
|
||||
subLinkObjectInit(db);
|
||||
insert(db, "parent", "5");
|
||||
insert(db, "link", "5", "10");
|
||||
insert(db, "subobject", "10", "1234");
|
||||
ParentLinkTestClass obj = DBBean.load(db, ParentLinkTestClass.class, 5);
|
||||
insert(db, "parent", "41");
|
||||
insert(db, "link", "41", "410");
|
||||
insert(db, "subobject", "410", "1234");
|
||||
ParentLinkTestClass obj = DBBean.load(db, ParentLinkTestClass.class, 41);
|
||||
|
||||
assertEquals(1, obj.subobjs.size());
|
||||
assertEquals((Long)10L, obj.subobjs.get(0).getId());
|
||||
assertEquals((Long)410L, obj.subobjs.get(0).getId());
|
||||
assertEquals(1234, obj.subobjs.get(0).intField);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multiSubLinkObjectLoad() throws SQLException {
|
||||
subLinkObjectInit(db);
|
||||
insert(db, "parent", "5");
|
||||
insert(db, "link", "5", "10");
|
||||
insert(db, "link", "5", "11");
|
||||
insert(db, "link", "5", "12");
|
||||
insert(db, "subobject", "10", "1001");
|
||||
insert(db, "subobject", "11", "1002");
|
||||
insert(db, "subobject", "12", "1003");
|
||||
ParentLinkTestClass obj = DBBean.load(db, ParentLinkTestClass.class, 5);
|
||||
insert(db, "parent", "42");
|
||||
insert(db, "link", "42", "420");
|
||||
insert(db, "link", "42", "421");
|
||||
insert(db, "link", "42", "422");
|
||||
insert(db, "subobject", "420", "1001");
|
||||
insert(db, "subobject", "421", "1002");
|
||||
insert(db, "subobject", "422", "1003");
|
||||
ParentLinkTestClass obj = DBBean.load(db, ParentLinkTestClass.class, 42);
|
||||
|
||||
assertEquals(3, obj.subobjs.size());
|
||||
assertEquals((Long)10L, obj.subobjs.get(0).getId());
|
||||
assertEquals((Long)420L, obj.subobjs.get(0).getId());
|
||||
assertEquals(1001, obj.subobjs.get(0).intField);
|
||||
assertEquals((Long)11L, obj.subobjs.get(1).getId());
|
||||
assertEquals((Long)421L, obj.subobjs.get(1).getId());
|
||||
assertEquals(1002, obj.subobjs.get(1).intField);
|
||||
assertEquals((Long)12L, obj.subobjs.get(2).getId());
|
||||
assertEquals((Long)422L, obj.subobjs.get(2).getId());
|
||||
assertEquals(1003, obj.subobjs.get(2).intField);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue