diff --git a/src/zutil/db/DBConnection.java b/src/zutil/db/DBConnection.java index 9f6da08..fffbf36 100755 --- a/src/zutil/db/DBConnection.java +++ b/src/zutil/db/DBConnection.java @@ -36,105 +36,105 @@ import java.util.logging.Level; import java.util.logging.Logger; public class DBConnection implements Closeable{ - private static final Logger logger = LogUtil.getLogger(); - - public enum DBMS{ - MySQL, - SQLite - } + private static final Logger logger = LogUtil.getLogger(); - // The connection - private Connection conn; - // The pool that this connection belongs to - private DBConnectionPool pool; - - - /** - * Creates an Connection from JNDI - * - * @param jndi the name of the connection, e.g. "jdbc/mysql" - */ - public DBConnection(String jndi) throws NamingException, SQLException{ - InitialContext ctx = new InitialContext(); - DataSource ds = (DataSource)ctx.lookup("java:comp/env/"+jndi); - this.conn = ds.getConnection(); + public enum DBMS{ + MySQL, + SQLite } - /** - * Creates an Connection to a MySQL server - * - * @param url is the URL of the MySQL server - * @param db is the database to connect to - * @param user is the user name - * @param password is the password - */ - public DBConnection(String url, String db, String user, String password) throws Exception{ - this(DBMS.MySQL, url, db, user, password); - } + // The connection + private Connection conn; + // The pool that this connection belongs to + private DBConnectionPool pool; - /** - * Creates an Connection to a DB server - * - * @param dbms is the DB type - * @param url is the URL of the MySQL server - * @param db is the database to connect to - * @param user is the user name - * @param password is the password - */ - public DBConnection(DBMS dbms, String url, String db, String user, String password) throws Exception{ - String dbms_name = initDriver(dbms); - conn = DriverManager.getConnection ("jdbc:"+dbms_name+"://"+url+"/"+db, user, password); - } - - /** - * Creates an Connection to a DB file - * - * @param dbms is the DB type - * @param db is the database to connect to - */ - public DBConnection(DBMS dbms, String db) throws Exception{ - String dbms_name = initDriver(dbms); - conn = DriverManager.getConnection ("jdbc:"+dbms_name+":"+db); - } - /** - * @return the underlying connection - */ - public Connection getConnection(){ - return conn; - } + /** + * Creates an Connection from JNDI + * + * @param jndi the name of the connection, e.g. "jdbc/mysql" + */ + public DBConnection(String jndi) throws NamingException, SQLException{ + InitialContext ctx = new InitialContext(); + DataSource ds = (DataSource)ctx.lookup("java:comp/env/"+jndi); + this.conn = ds.getConnection(); + } - /** - * Initiates the DB driver and returns its protocol name. - * - * @param db is the DB type - * @return the protocol name of the DBMS - */ - public static String initDriver(DBMS db) throws InstantiationException, IllegalAccessException, ClassNotFoundException{ - switch(db){ - case MySQL: - Class.forName("com.mysql.jdbc.Driver").newInstance(); - DriverManager.setLoginTimeout(10); - return "mysql"; - case SQLite: - Class.forName("org.sqlite.JDBC"); - return "sqlite"; - default: - return null; - } - } + /** + * Creates an Connection to a MySQL server + * + * @param url is the URL of the MySQL server + * @param db is the database to connect to + * @param user is the user name + * @param password is the password + */ + public DBConnection(String url, String db, String user, String password) throws Exception{ + this(DBMS.MySQL, url, db, user, password); + } - /** - * @return the last inserted id or -1 if there was an error - */ - public long getLastInsertID(){ - try{ - return exec("SELECT LAST_INSERT_ID()", new SimpleSQLResult()); - }catch(SQLException e){ - logger.log(Level.WARNING, null, e); - } - return -1; - } + /** + * Creates an Connection to a DB server + * + * @param dbms is the DB type + * @param url is the URL of the MySQL server + * @param db is the database to connect to + * @param user is the user name + * @param password is the password + */ + public DBConnection(DBMS dbms, String url, String db, String user, String password) throws Exception{ + String dbms_name = initDriver(dbms); + conn = DriverManager.getConnection ("jdbc:"+dbms_name+"://"+url+"/"+db, user, password); + } + + /** + * Creates an Connection to a DB file + * + * @param dbms is the DB type + * @param db is the database to connect to + */ + public DBConnection(DBMS dbms, String db) throws Exception{ + String dbms_name = initDriver(dbms); + conn = DriverManager.getConnection ("jdbc:"+dbms_name+":"+db); + } + + /** + * @return the underlying connection + */ + public Connection getConnection(){ + return conn; + } + + /** + * Initiates the DB driver and returns its protocol name. + * + * @param db is the DB type + * @return the protocol name of the DBMS + */ + public static String initDriver(DBMS db) throws InstantiationException, IllegalAccessException, ClassNotFoundException{ + switch(db){ + case MySQL: + Class.forName("com.mysql.jdbc.Driver").newInstance(); + DriverManager.setLoginTimeout(10); + return "mysql"; + case SQLite: + Class.forName("org.sqlite.JDBC"); + return "sqlite"; + default: + return null; + } + } + + /** + * @return the last inserted id or -1 if there was an error + */ + public long getLastInsertID(){ + try{ + return exec("SELECT LAST_INSERT_ID()", new SimpleSQLResult()); + }catch(SQLException e){ + logger.log(Level.WARNING, null, e); + } + return -1; + } /** * @return the last inserted id or -1 if there was an error */ @@ -159,126 +159,119 @@ public class DBConnection implements Closeable{ return -1; } - /** - * Runs a Prepared Statement.
- * NOTE: Don't forget to close the PreparedStatement or it can lead to memory leaks - * - * @param sql is the SQL query to run - * @return An PreparedStatement - */ - public PreparedStatement getPreparedStatement(String sql) throws SQLException{ - return conn.prepareStatement(sql); - } + /** + * Runs a Prepared Statement.
+ * NOTE: Don't forget to close the PreparedStatement or it can lead to memory leaks + * + * @param sql is the SQL query to run + * @return an PreparedStatement + */ + public PreparedStatement getPreparedStatement(String sql) throws SQLException{ + if (sql.regionMatches(true, 0, "INSERT", 0, 6)) + return conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS); + return conn.prepareStatement(sql); + } - /** - * NOTE: Don't forget to close the Statement or it can lead to memory leaks - * - * @return an Statement for the DB - */ - public Statement getStatement() throws SQLException{ - return conn.createStatement(); - } + /** + * Executes a SQL query and cleans up after itself. + * + * @param query is the query + * @return update count or -1 if the query is not an update query + */ + public int exec(String query) throws SQLException { + PreparedStatement stmt = getPreparedStatement( query ); + return exec(stmt); + } - /** - * Executes an query and cleans up after itself. - * - * @param query is the query - * @return update count or -1 if the query is not an update query - */ - public int exec(String query) throws SQLException { - PreparedStatement stmt = getPreparedStatement( query ); - return exec(stmt); - } - - /** - * Executes an query and cleans up after itself. - * - * @param stmt is the query - * @return update count or -1 if the query is not an update query - */ - public static int exec(PreparedStatement stmt) throws SQLException { - Integer ret = exec(stmt, new SQLResultHandler(){ - public Integer handleQueryResult(Statement stmt, ResultSet result) { - try { - if(stmt != null) - return stmt.getUpdateCount(); - else - return -1; - } catch (SQLException e) { - logger.log(Level.WARNING, null, e); - } - return -1; - } - }); - - if(ret != null) - return ret; - return -1; - } - - /** - * Executes an query and cleans up after itself. - * - * @param - * @param query is the query - * @param handler is the result handler - * @return update count or -1 if the query is not an update query - */ - public T exec(String query, SQLResultHandler handler) throws SQLException { - PreparedStatement stmt = getPreparedStatement( query ); - return exec(stmt, handler); - } + /** + * Executes an query and cleans up after itself. + * + * @param stmt is the query + * @return update count or -1 if the query is not an update query + */ + public static int exec(PreparedStatement stmt) throws SQLException { + Integer ret = exec(stmt, new SQLResultHandler(){ + public Integer handleQueryResult(Statement stmt, ResultSet result) { + try { + if(stmt != null) + return stmt.getUpdateCount(); + else + return -1; + } catch (SQLException e) { + logger.log(Level.WARNING, null, e); + } + return -1; + } + }); - /** - * Executes a query and cleans up after itself. - * - * @param stmt is the query to run - * @param handler is the result handler that will be called with the output of the execution - * @return the object from the handler - */ - public static T exec(PreparedStatement stmt, SQLResultHandler handler) throws SQLException{ - try{ - // Execute - boolean isResultSet = stmt.execute(); + if(ret != null) + return ret; + return -1; + } - // Handle result - if( handler != null ){ - ResultSet result = null; - try{ - if(isResultSet){ - result = stmt.getResultSet(); - return handler.handleQueryResult(stmt, result); - } - else - return null; - }catch(SQLException e){ - logger.log(Level.WARNING, null, e); - }finally{ - if(result != null){ - try { - result.close(); - } catch (SQLException e) { - logger.log(Level.WARNING, null, e); - } - result = null; - } - } - } - }catch(SQLException e){ - logger.log(Level.WARNING, null, e); - // Cleanup - } finally { - if (stmt != null) { - try { - stmt.close(); - } catch (SQLException e) { - logger.log(Level.WARNING, null, e); - } - stmt = null; - } - } - return null; - } + /** + * Executes an query and cleans up after itself. + * + * @param + * @param query is the query + * @param handler is the result handler + * @return update count or -1 if the query is not an update query + */ + public T exec(String query, SQLResultHandler handler) throws SQLException { + PreparedStatement stmt = getPreparedStatement( query ); + return exec(stmt, handler); + } + + /** + * Executes a query and cleans up after itself. + * + * @param stmt is the query to run + * @param handler is the result handler that will be called with the output of the execution + * @return the object from the handler + */ + public static T exec(PreparedStatement stmt, SQLResultHandler handler) throws SQLException { + try{ + // Execute + boolean isResultSet = stmt.execute(); + + // Handle result + if( handler != null ){ + ResultSet result = null; + try{ + if(isResultSet){ + result = stmt.getResultSet(); + return handler.handleQueryResult(stmt, result); + } + else + return null; + }catch(SQLException e){ + logger.log(Level.WARNING, null, e); + }finally{ + if(result != null){ + try { + result.close(); + } catch (SQLException e) { + logger.log(Level.WARNING, null, e); + } + result = null; + } + } + } + }catch(SQLException e){ + logger.log(Level.WARNING, null, e); + // Cleanup + } finally { + if (stmt != null) { + try { + stmt.close(); + } catch (SQLException e) { + logger.log(Level.WARNING, null, e); + } + stmt = null; + } + } + return null; + } /** * Executes an query and cleans up after itself. @@ -306,60 +299,60 @@ public class DBConnection implements Closeable{ return new int[0]; } - /** - * Sets the pool that this connection belongs to - * - * @param pool is the pool - */ - protected void setPool(DBConnectionPool pool){ - if( pool != null ) - pool.removeConnection(this); - this.pool = pool; - } + /** + * Sets the pool that this connection belongs to + * + * @param pool is the pool + */ + protected void setPool(DBConnectionPool pool){ + if( pool != null ) + pool.removeConnection(this); + this.pool = pool; + } - /** - * Checks if the DB Connection is valid and functioning - * - * @return true or false depending on the validity of the connection - */ - public boolean valid(){ - try { - conn.getMetaData(); - return !conn.isClosed(); - }catch (Exception e) { - return false; - } - } + /** + * Checks if the DB Connection is valid and functioning + * + * @return true or false depending on the validity of the connection + */ + public boolean valid(){ + try { + conn.getMetaData(); + return !conn.isClosed(); + }catch (Exception e) { + return false; + } + } - /** - * Disconnects from the database or releases the connection back to the pool - */ - public void close(){ - if(pool!=null){ - pool.releaseConnection(this); - conn = null; - } - else{ - forceClose(); - } - } + /** + * Disconnects from the database or releases the connection back to the pool + */ + public void close(){ + if(pool != null){ + pool.releaseConnection(this); + conn = null; + } + else{ + forceClose(); + } + } - /** - * Disconnects from the database - */ - public void forceClose(){ - if (conn != null) { - try { - if( !conn.isClosed() ) - conn.close(); - } catch (SQLException e) { - logger.log(Level.WARNING, null, e); - } - conn = null; - } - } + /** + * Disconnects from the database + */ + public void forceClose(){ + if (conn != null) { + try { + if( !conn.isClosed() ) + conn.close(); + } catch (SQLException e) { + logger.log(Level.WARNING, null, e); + } + conn = null; + } + } - public boolean equals(Object o){ - return conn.equals(o); - } + public boolean equals(Object o){ + return conn.equals(o); + } } diff --git a/src/zutil/db/bean/DBBean.java b/src/zutil/db/bean/DBBean.java index 8b08a80..c4c045a 100755 --- a/src/zutil/db/bean/DBBean.java +++ b/src/zutil/db/bean/DBBean.java @@ -64,85 +64,85 @@ import java.util.logging.Logger; * @author Ziver */ public abstract class DBBean { - private static final Logger logger = LogUtil.getLogger(); + private static final Logger logger = LogUtil.getLogger(); - /** - * Sets the name of the table in the database - */ - @Retention(RetentionPolicy.RUNTIME) - @Target(ElementType.TYPE) - public @interface DBTable { - /** This is the name of the table, SQL rules apply should not contain any strange characters or spaces **/ - String value(); - /** Change the id column name of the bean, default column name is "id", SQL rules apply should not contain any strange characters or spaces **/ - String idColumn() default "id"; - /** Sets if the fields in the super classes is also part of the bean **/ - boolean superBean() default false; - } + /** + * Sets the name of the table in the database + */ + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.TYPE) + public @interface DBTable { + /** This is the name of the table, SQL rules apply should not contain any strange characters or spaces **/ + String value(); + /** Change the id column name of the bean, default column name is "id", SQL rules apply should not contain any strange characters or spaces **/ + String idColumn() default "id"; + /** Sets if the fields in the super classes is also part of the bean **/ + boolean superBean() default false; + } - /** - * 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(); - } + /** + * 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 */ - String table(); - /** The class of the linked bean */ - Class beanClass(); - /** 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 ""; - } + /** + * 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 */ + String table(); + /** The class of the linked bean */ + Class beanClass(); + /** 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 ""; + } /** A unique id of the bean **/ private Long id; - /** This lock is for preventing recursive loops and concurrency when saving */ - protected ReentrantLock saveLock; - /** This value is for preventing recursive loops when updating */ - protected ReentrantLock readLock; + /** This lock is for preventing recursive loops and concurrency when saving */ + protected ReentrantLock saveLock; + /** This value is for preventing recursive loops when updating */ + protected ReentrantLock readLock; - protected DBBean(){ - DBBeanConfig.getBeanConfig(this.getClass()); + protected DBBean(){ + DBBeanConfig.getBeanConfig(this.getClass()); saveLock = new ReentrantLock(); readLock = new ReentrantLock(); - } + } - /** - * Saves the bean and all its sub beans to the DB - * - * @param db is the DBMS connection - */ - public void save(DBConnection db) throws SQLException{ - save( db, true ); - } - - /** - * Saves the bean to the DB - * - * @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{ - if (saveLock.isHeldByCurrentThread()) // If the current thread already has a lock then this - return; // is a recursive call and we do not need to do anything - else if (saveLock.tryLock()) { + /** + * Saves the bean and all its sub beans to the DB + * + * @param db is the DBMS connection + */ + public void save(DBConnection db) throws SQLException{ + save( db, true ); + } + + /** + * Saves the bean to the DB + * + * @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{ + if (saveLock.isHeldByCurrentThread()) // If the current thread already has a lock then this + return; // is a recursive call and we do not need to do anything + else if (saveLock.tryLock()) { Class c = this.getClass(); DBBeanConfig config = DBBeanConfig.getBeanConfig(c); try { @@ -153,13 +153,13 @@ public abstract class DBBean { StringBuilder sqlCols = new StringBuilder(); StringBuilder sqlValues = new StringBuilder(); for (DBBeanFieldConfig field : config.getFields()) { - if (sqlCols.length() > 0) - sqlCols.append(", "); - sqlCols.append(field.getName()); + if (sqlCols.length() > 0) + sqlCols.append(", "); + sqlCols.append(field.getName()); - if (sqlValues.length() > 0) - sqlValues.append(", "); - sqlValues.append("?"); + if (sqlValues.length() > 0) + sqlValues.append(", "); + sqlValues.append("?"); } if (config.getFields().size() > 0) { // is there any fields? query.append(" (").append(sqlCols).append(")"); @@ -171,10 +171,10 @@ public abstract class DBBean { query.append("UPDATE ").append(config.getTableName()); StringBuilder sqlSets = new StringBuilder(); for (DBBeanFieldConfig field : config.getFields()) { - if (sqlSets.length() > 0) - sqlSets.append(", "); - sqlSets.append(field.getName()); - sqlSets.append("=?"); + if (sqlSets.length() > 0) + sqlSets.append(", "); + sqlSets.append(field.getName()); + sqlSets.append("=?"); } query.append(" SET ").append(sqlSets); query.append(" WHERE ").append(config.getIdColumnName()).append("=?"); @@ -264,11 +264,11 @@ public abstract class DBBean { saveLock.unlock(); } } else { - // If we have concurrent saves, only save once and skip the other threads + // If we have concurrent saves, only save once and skip the other threads saveLock.lock(); saveLock.unlock(); } - } + } /** @@ -277,18 +277,18 @@ public abstract class DBBean { public void delete(DBConnection db) throws SQLException{ delete(db, true); } - /** - * Deletes the bean from the DB and the links to sub beans. + /** + * 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, boolean recursive) throws SQLException{ - Class c = this.getClass(); - DBBeanConfig config = DBBeanConfig.getBeanConfig( c ); - if( this.getId() == null ) - throw new NullPointerException("ID field is null! (Has the bean been saved?)"); + */ + public void delete(DBConnection db, boolean recursive) throws SQLException{ + Class c = this.getClass(); + DBBeanConfig config = DBBeanConfig.getBeanConfig( c ); + if( this.getId() == null ) + throw new NullPointerException("ID field is null! (Has the bean been saved?)"); - // Delete sub beans + // Delete sub beans for (DBBeanSubBeanConfig subBeanField : config.getSubBeans()) { List list = (List) subBeanField.getValue(this); if (list != null) { @@ -309,130 +309,130 @@ public abstract class DBBean { } // 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 ); - stmt.setLong(1, this.getId() ); - DBConnection.exec(stmt); + 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 ); + stmt.setLong(1, this.getId() ); + DBConnection.exec(stmt); - // Clear cache and reset id - DBBeanCache.remove(this); - this.id = null; - } - - /** - * Loads all rows from the table into a LinkedList - * - * @param is the class of the bean - * @param c is the class of the bean - * @return a LinkedList with all the beans in the DB - */ - public static List load(DBConnection db, Class c) throws SQLException { - // Initiate a BeanConfig if there is non - DBBeanConfig config = DBBeanConfig.getBeanConfig( c ); - // Generate query - String sql = "SELECT * FROM "+config.getTableName(); - logger.finest("Load all Beans("+c.getName()+") query: "+sql); - PreparedStatement stmt = db.getPreparedStatement( sql ); - // Run query - List list = DBConnection.exec(stmt, DBBeanSQLResultHandler.createList(c, db) ); - return list; - } - - /** - * Loads a specific instance of the bean from the table with the specific id - * - * @param is the class of the bean - * @param c is the class of the bean - * @param id is the id value of the bean - * @return a DBBean Object with the specific id or null if the id was not found - */ - public static T load(DBConnection db, Class c, long id) throws SQLException { - // Initiate a BeanConfig if there is non - DBBeanConfig config = DBBeanConfig.getBeanConfig( c ); - // Generate query - 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 ); - // Run query - T obj = DBConnection.exec(stmt, DBBeanSQLResultHandler.create(c, db) ); - return obj; - } - - /** - * Creates a specific table for the given Bean, - * WARNING: Experimental - */ - public static void create(DBConnection sql, Class c) throws SQLException{ - DBBeanConfig config = DBBeanConfig.getBeanConfig( c ); - - // Generate the SQL - StringBuilder query = new StringBuilder(); - query.append("CREATE TABLE "+config.getTableName()+" ( "); - - // ID - query.append(" ").append(config.getIdColumnName()).append(" "); - query.append( classToDBType( Long.class ) ); - query.append(" PRIMARY KEY AUTO_INCREMENT, "); - - for( DBBeanFieldConfig field : config.getFields() ){ - query.append(" "); - query.append(field.getName()); - query.append(classToDBType(c)); - query.append(", "); - } - query.delete(query.length()-2, query.length()); - query.append(")"); - - logger.finest("Create Bean("+c.getName()+") query: "+sql.toString()); - PreparedStatement stmt = sql.getPreparedStatement( sql.toString() ); - - // Execute the SQL - DBConnection.exec(stmt); - } - - 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"; - else if(c == Integer.class) return "INTEGER"; - else if(c == int.class) return "INTEGER"; - else if(c == BigInteger.class) return "BIGINT"; - else if(c == Long.class) return "DECIMAL"; - else if(c == long.class) return "DECIMAL"; - else if(c == Float.class) return "DOUBLE"; - else if(c == float.class) return "DOUBLE"; - else if(c == Double.class) return "DOUBLE"; - else if(c == double.class) return "DOUBLE"; - else if(c == BigDecimal.class) return "DECIMAL"; - else if(c == Boolean.class) return "BOOLEAN"; - else if(c == boolean.class) return "BOOLEAN"; - else if(c == Byte.class) return "BINARY(1)"; - else if(c == byte.class) return "BINARY(1)"; - else if(c == Timestamp.class) return "DATETIME"; - else if(DBBean.class.isAssignableFrom(c)) - return classToDBType(Long.class); - return null; - } + // Clear cache and reset id + DBBeanCache.remove(this); + this.id = null; + } /** - * @return the bean id or null if the bean has not bean saved yet - */ - public final Long getId(){ - return id; - } + * Loads all rows from the table into a LinkedList + * + * @param is the class of the bean + * @param c is the class of the bean + * @return a LinkedList with all the beans in the DB + */ + public static List load(DBConnection db, Class c) throws SQLException { + // Initiate a BeanConfig if there is non + DBBeanConfig config = DBBeanConfig.getBeanConfig( c ); + // Generate query + String sql = "SELECT * FROM "+config.getTableName(); + logger.finest("Load all Beans("+c.getName()+") query: "+sql); + PreparedStatement stmt = db.getPreparedStatement( sql ); + // Run query + List list = DBConnection.exec(stmt, DBBeanSQLResultHandler.createList(c, db) ); + return list; + } + + /** + * Loads a specific instance of the bean from the table with the specific id + * + * @param is the class of the bean + * @param c is the class of the bean + * @param id is the id value of the bean + * @return a DBBean Object with the specific id or null if the id was not found + */ + public static T load(DBConnection db, Class c, long id) throws SQLException { + // Initiate a BeanConfig if there is non + DBBeanConfig config = DBBeanConfig.getBeanConfig( c ); + // Generate query + 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 ); + // Run query + T obj = DBConnection.exec(stmt, DBBeanSQLResultHandler.create(c, db) ); + return obj; + } + + /** + * Creates a specific table for the given Bean, + * WARNING: Experimental + */ + public static void create(DBConnection sql, Class c) throws SQLException{ + DBBeanConfig config = DBBeanConfig.getBeanConfig( c ); + + // Generate the SQL + StringBuilder query = new StringBuilder(); + query.append("CREATE TABLE "+config.getTableName()+" ( "); + + // ID + query.append(" ").append(config.getIdColumnName()).append(" "); + query.append( classToDBType( Long.class ) ); + query.append(" PRIMARY KEY AUTO_INCREMENT, "); + + for( DBBeanFieldConfig field : config.getFields() ){ + query.append(" "); + query.append(field.getName()); + query.append(classToDBType(c)); + query.append(", "); + } + query.delete(query.length()-2, query.length()); + query.append(")"); + + logger.finest("Create Bean("+c.getName()+") query: "+sql.toString()); + PreparedStatement stmt = sql.getPreparedStatement( sql.toString() ); + + // Execute the SQL + DBConnection.exec(stmt); + } + + 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"; + else if(c == Integer.class) return "INTEGER"; + else if(c == int.class) return "INTEGER"; + else if(c == BigInteger.class) return "BIGINT"; + else if(c == Long.class) return "DECIMAL"; + else if(c == long.class) return "DECIMAL"; + else if(c == Float.class) return "DOUBLE"; + else if(c == float.class) return "DOUBLE"; + else if(c == Double.class) return "DOUBLE"; + else if(c == double.class) return "DOUBLE"; + else if(c == BigDecimal.class) return "DECIMAL"; + else if(c == Boolean.class) return "BOOLEAN"; + else if(c == boolean.class) return "BOOLEAN"; + else if(c == Byte.class) return "BINARY(1)"; + else if(c == byte.class) return "BINARY(1)"; + else if(c == Timestamp.class) return "DATETIME"; + else if(DBBean.class.isAssignableFrom(c)) + return classToDBType(Long.class); + return null; + } + + /** + * @return the bean id or null if the bean has not bean saved yet + */ + public final Long getId(){ + return id; + } final void setId(Long id){ this.id = id; } - + ////////////////// EXTENDABLE METHODS ///////////////////////// - /** - * Will be called whenever the bean has been updated from the database. - */ - protected void postUpdateAction(){} + /** + * Will be called whenever the bean has been updated from the database. + */ + protected void postUpdateAction(){} }