diff --git a/Zutil.jar b/Zutil.jar index 710b214..7466c03 100755 Binary files a/Zutil.jar and b/Zutil.jar differ diff --git a/src/zutil/db/bean/DBBean.java b/src/zutil/db/bean/DBBean.java index 35ae080..ad75c8a 100755 --- a/src/zutil/db/bean/DBBean.java +++ b/src/zutil/db/bean/DBBean.java @@ -38,8 +38,6 @@ import java.math.BigInteger; import java.sql.PreparedStatement; import java.sql.SQLException; import java.sql.Timestamp; -import java.util.ArrayList; -import java.util.HashMap; import java.util.List; import java.util.NoSuchElementException; import java.util.logging.Level; @@ -87,104 +85,41 @@ public abstract class DBBean { } /** - * Sets the name of the table that links different DBBeans together + * Can be used if the column name is different from the field name. + */ + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.FIELD) + public @interface DBColumn { + /** This is the name of the column in the database for the specified field. SQL rules apply, should not contain any strange characters or spaces **/ + String value(); + } + + /** + * Should be used for fields with lists of DBBeans. */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface DBLinkTable { - /** The name of the Link table, SQL rules apply should not contain any strange characters or spaces */ + /** The name of the Link table, SQL rules apply, should not contain any strange characters or spaces */ String table(); /** The class of the linked bean */ Class 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 main objects id, SQL rules apply, should not contain any strange characters or spaces */ String idColumn() default ""; } - /** - * A Class that contains information about a bean - */ - protected static class DBBeanConfig{ - /** The name of the table in the DB **/ - protected String tableName; - /** The name of the id column **/ - protected String idColumn; - /** All the fields in the bean **/ - protected ArrayList fields; - protected DBBeanConfig(){ - fields = new ArrayList(); - } - } - - /** This is a cache of all the initialized beans */ - private static HashMap beanConfigs = new HashMap(); /** This value is for preventing recursive loops when saving */ protected boolean processing_save; /** This value is for preventing recursive loops when updating */ protected boolean processing_update; protected DBBean(){ - if( !beanConfigs.containsKey( this.getClass() ) ) - initBeanConfig( this.getClass() ); + DBBeanConfig.getBeanConfig(this.getClass()); processing_save = false; processing_update = false; } - /** - * @return all the fields except the ID field - */ - public static ArrayList getFields(Class c){ - if( !beanConfigs.containsKey( c.getName() ) ) - initBeanConfig( c ); - return beanConfigs.get( c.getName() ).fields; - } - - /** - * @return the configuration object for the specified class - */ - protected static DBBeanConfig getBeanConfig(Class c){ - if( !beanConfigs.containsKey( c.getName() ) ) - initBeanConfig( c ); - return beanConfigs.get( c.getName() ); - } - - /** - * Caches the fields - */ - private static void initBeanConfig(Class c){ - logger.fine("Initiating new DBBeanConfig( "+c.getName()+" )"); - DBBeanConfig config = new DBBeanConfig(); - // Find the table name - DBTable tableAnn = c.getAnnotation(DBTable.class); - if( tableAnn != null ){ - config.tableName = tableAnn.value(); - config.idColumn = tableAnn.idColumn(); - } - else{ - config.tableName = c.getSimpleName(); - config.idColumn = "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(); - 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( tableAnn == null || !tableAnn.superBean() ) - break; - } - - beanConfigs.put(c.getName(), config); - } /** * Saves the object and all the sub objects to the DB @@ -207,7 +142,7 @@ public abstract class DBBean { return; processing_save = true; Class c = this.getClass(); - DBBeanConfig config = getBeanConfig( c ); + DBBeanConfig config = DBBeanConfig.getBeanConfig( c ); try { Long id = this.getId(); // Generate the SQL @@ -218,7 +153,7 @@ public abstract class DBBean { for( Field field : config.fields ){ if( !List.class.isAssignableFrom(field.getType()) ){ query.append(" "); - query.append(field.getName()); + query.append(DBBeanConfig.getFieldName(field)); query.append(","); } } @@ -238,7 +173,7 @@ public abstract class DBBean { for( Field field : config.fields ){ if( !List.class.isAssignableFrom(field.getType()) ){ query.append(" "); - query.append(field.getName()); + query.append(DBBeanConfig.getFieldName(field)); query.append("=?,"); } } @@ -308,7 +243,7 @@ public abstract class DBBean { } // Get the Sub object configuration if(subConfig == null){ - subConfig = getBeanConfig( subobj.getClass() ); + subConfig = DBBeanConfig.getBeanConfig( subobj.getClass() ); sub_idcol = subConfig.idColumn; } // Save links in link table @@ -342,7 +277,7 @@ public abstract class DBBean { */ public void delete(DBConnection db) throws SQLException{ Class c = this.getClass(); - DBBeanConfig config = getBeanConfig( c ); + DBBeanConfig config = DBBeanConfig.getBeanConfig( c ); if( this.getId() == null ) throw new NoSuchElementException("ID field is null( Has the bean been saved?)!"); @@ -366,7 +301,7 @@ public abstract class DBBean { */ public static List load(DBConnection db, Class c) throws SQLException { // Initiate a BeanConfig if there is non - DBBeanConfig config = getBeanConfig( c ); + DBBeanConfig config = DBBeanConfig.getBeanConfig( c ); // Generate query String sql = "SELECT * FROM "+config.tableName; logger.fine("Load All query("+c.getName()+"): "+sql); @@ -386,7 +321,7 @@ public abstract class DBBean { */ public static T load(DBConnection db, Class c, long id) throws SQLException { // Initiate a BeanConfig if there is non - DBBeanConfig config = getBeanConfig( c ); + DBBeanConfig config = DBBeanConfig.getBeanConfig( c ); // Generate query String sql = "SELECT * FROM "+config.tableName+" WHERE "+config.idColumn+"=? LIMIT 1"; logger.fine("Load query("+c.getName()+" id:"+id+"): "+sql); @@ -402,7 +337,7 @@ public abstract class DBBean { * WARNING: Experimental */ public static void create(DBConnection sql, Class c) throws SQLException{ - DBBeanConfig config = getBeanConfig( c ); + DBBeanConfig config = DBBeanConfig.getBeanConfig( c ); // Generate the SQL StringBuilder query = new StringBuilder(); @@ -415,7 +350,7 @@ public abstract class DBBean { for( Field field : config.fields ){ query.append(" "); - query.append( field.getName() ); + query.append( DBBeanConfig.getFieldName(field) ); query.append( classToDBName(c) ); query.append(", "); } @@ -504,7 +439,7 @@ public abstract class DBBean { } } - /** + /** * @return the object id or null if the bean has not bean saved yet */ public Long getId(){ @@ -517,7 +452,12 @@ public abstract class DBBean { public static void cancelGBC(){ DBBeanSQLResultHandler.cancelGBC(); } - + + + + + ////////////////// EXTENDABLE METHODS ///////////////////////// + /** * Will be called whenever the bean has been updated from the database. */ diff --git a/src/zutil/db/bean/DBBeanConfig.java b/src/zutil/db/bean/DBBeanConfig.java new file mode 100755 index 0000000..1573162 --- /dev/null +++ b/src/zutil/db/bean/DBBeanConfig.java @@ -0,0 +1,88 @@ +package zutil.db.bean; + +import zutil.log.LogUtil; + +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.logging.Logger; + +/** + * A Class that contains information about a bean + */ +class DBBeanConfig{ + private static final Logger logger = LogUtil.getLogger(); + /** This is a cache of all the initialized beans */ + private static HashMap beanConfigs = new HashMap(); + + + /** The name of the table in the DB **/ + protected String tableName; + /** The name of the id column **/ + protected String idColumn; + /** All the fields in the bean **/ + protected ArrayList fields; + + protected DBBeanConfig(){ + fields = new ArrayList(); + } + + + + /** + * @return the configuration object for the specified class + */ + protected static DBBeanConfig getBeanConfig(Class c){ + if( !beanConfigs.containsKey( c.getName() ) ) + initBeanConfig( c ); + return beanConfigs.get( c.getName() ); + } + + /** + * Caches the fields + */ + private static void initBeanConfig(Class c){ + logger.fine("Initiating new DBBeanConfig( "+c.getName()+" )"); + DBBeanConfig config = new DBBeanConfig(); + // Find the table name + DBBean.DBTable tableAnn = c.getAnnotation(DBBean.DBTable.class); + if( tableAnn != null ){ + config.tableName = tableAnn.value(); + config.idColumn = tableAnn.idColumn(); + } + else{ + config.tableName = c.getSimpleName(); + config.idColumn = "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(); + 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( tableAnn == null || !tableAnn.superBean() ) + break; + } + + beanConfigs.put(c.getName(), config); + } + + protected static String getFieldName(Field field){ + String name = null; + if(field.getDeclaredAnnotation(DBBean.DBColumn.class) != null) + name = field.getDeclaredAnnotation(DBBean.DBColumn.class).value(); + else + name = field.getName(); + return name; + } +} \ No newline at end of file diff --git a/src/zutil/db/bean/DBBeanSQLResultHandler.java b/src/zutil/db/bean/DBBeanSQLResultHandler.java index e2124bc..f6b4511 100755 --- a/src/zutil/db/bean/DBBeanSQLResultHandler.java +++ b/src/zutil/db/bean/DBBeanSQLResultHandler.java @@ -26,7 +26,6 @@ package zutil.db.bean; import zutil.db.DBConnection; import zutil.db.SQLResultHandler; -import zutil.db.bean.DBBean.DBBeanConfig; import zutil.db.bean.DBBean.DBLinkTable; import zutil.log.LogUtil; @@ -114,7 +113,7 @@ public class DBBeanSQLResultHandler implements SQLResultHandler{ this.bean_class = cl; this.list = list; this.db = db; - this.bean_config = DBBean.getBeanConfig( cl ); + this.bean_config = DBBeanConfig.getBeanConfig( cl ); // Initiate DBBeanGarbageCollector if( timer == null ){ @@ -207,7 +206,7 @@ public class DBBeanSQLResultHandler implements SQLResultHandler{ * @return a new instance of the bean */ protected DBBean createBean(ResultSet result) throws SQLException{ - try { + try { Long id = result.getLong( "id" ); DBBean obj = getCachedDBBean(bean_class, id, result); if( obj != null ) @@ -222,6 +221,8 @@ public class DBBeanSQLResultHandler implements SQLResultHandler{ // Update fields updateBean( result, obj ); return obj; + } catch (SQLException e) { + throw e; } catch (Exception e) { throw new SQLException(e); } @@ -240,7 +241,7 @@ public class DBBeanSQLResultHandler implements SQLResultHandler{ obj.processing_update = true; // Get the rest for( Field field : bean_config.fields ){ - String name = field.getName(); + String name = DBBeanConfig.getFieldName(field); // Another DBBean class if( DBBean.class.isAssignableFrom( field.getType() )){ @@ -257,7 +258,7 @@ public class DBBeanSQLResultHandler implements SQLResultHandler{ field.getAnnotation( DBLinkTable.class ) != null){ if(db != null){ DBLinkTable linkTable = field.getAnnotation( DBLinkTable.class ); - DBBeanConfig subConfig = DBBean.getBeanConfig( linkTable.beanClass() ); + DBBeanConfig subConfig = DBBeanConfig.getBeanConfig( linkTable.beanClass() ); String linkTableName = linkTable.table(); String subTable = subConfig.tableName; String idcol = (linkTable.idColumn().isEmpty() ? bean_config.tableName : linkTable.idColumn() ); @@ -277,8 +278,6 @@ public class DBBeanSQLResultHandler implements SQLResultHandler{ else obj.setFieldValue(field, result.getObject(name)); } - } catch (Exception e) { - throw new SQLException(e); } finally{ obj.processing_update = false; }