fixed last inserted id issue

This commit is contained in:
Ziver Koc 2017-08-21 16:05:22 +02:00
parent 86ce0990c6
commit c5c135320f
2 changed files with 452 additions and 459 deletions

View file

@ -36,105 +36,105 @@ import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
public class DBConnection implements Closeable{ public class DBConnection implements Closeable{
private static final Logger logger = LogUtil.getLogger(); private static final Logger logger = LogUtil.getLogger();
public enum DBMS{
MySQL,
SQLite
}
// The connection public enum DBMS{
private Connection conn; MySQL,
// The pool that this connection belongs to SQLite
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();
} }
/** // The connection
* Creates an Connection to a MySQL server private Connection conn;
* // The pool that this connection belongs to
* @param url is the URL of the MySQL server private DBConnectionPool pool;
* @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);
}
/**
* 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 * Creates an Connection from JNDI
*/ *
public Connection getConnection(){ * @param jndi the name of the connection, e.g. "jdbc/mysql"
return conn; */
} 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. * Creates an Connection to a MySQL server
* *
* @param db is the DB type * @param url is the URL of the MySQL server
* @return the protocol name of the DBMS * @param db is the database to connect to
*/ * @param user is the user name
public static String initDriver(DBMS db) throws InstantiationException, IllegalAccessException, ClassNotFoundException{ * @param password is the password
switch(db){ */
case MySQL: public DBConnection(String url, String db, String user, String password) throws Exception{
Class.forName("com.mysql.jdbc.Driver").newInstance(); this(DBMS.MySQL, url, db, user, password);
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 * Creates an Connection to a DB server
*/ *
public long getLastInsertID(){ * @param dbms is the DB type
try{ * @param url is the URL of the MySQL server
return exec("SELECT LAST_INSERT_ID()", new SimpleSQLResult<Long>()); * @param db is the database to connect to
}catch(SQLException e){ * @param user is the user name
logger.log(Level.WARNING, null, e); * @param password is the password
} */
return -1; 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<Long>());
}catch(SQLException e){
logger.log(Level.WARNING, null, e);
}
return -1;
}
/** /**
* @return the last inserted id or -1 if there was an error * @return the last inserted id or -1 if there was an error
*/ */
@ -159,126 +159,119 @@ public class DBConnection implements Closeable{
return -1; return -1;
} }
/** /**
* Runs a Prepared Statement.<br> * Runs a Prepared Statement.<br>
* <b>NOTE:</b> Don't forget to close the PreparedStatement or it can lead to memory leaks * <b>NOTE:</b> Don't forget to close the PreparedStatement or it can lead to memory leaks
* *
* @param sql is the SQL query to run * @param sql is the SQL query to run
* @return An PreparedStatement * @return an PreparedStatement
*/ */
public PreparedStatement getPreparedStatement(String sql) throws SQLException{ public PreparedStatement getPreparedStatement(String sql) throws SQLException{
return conn.prepareStatement(sql); if (sql.regionMatches(true, 0, "INSERT", 0, 6))
} return conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
return conn.prepareStatement(sql);
}
/** /**
* <b>NOTE:</b> Don't forget to close the Statement or it can lead to memory leaks * Executes a SQL query and cleans up after itself.
* *
* @return an Statement for the DB * @param query is the query
*/ * @return update count or -1 if the query is not an update query
public Statement getStatement() throws SQLException{ */
return conn.createStatement(); public int exec(String query) throws SQLException {
} PreparedStatement stmt = getPreparedStatement( query );
return exec(stmt);
}
/** /**
* Executes an query and cleans up after itself. * Executes an query and cleans up after itself.
* *
* @param query is the query * @param stmt is the query
* @return update count or -1 if the query is not an update query * @return update count or -1 if the query is not an update query
*/ */
public int exec(String query) throws SQLException { public static int exec(PreparedStatement stmt) throws SQLException {
PreparedStatement stmt = getPreparedStatement( query ); Integer ret = exec(stmt, new SQLResultHandler<Integer>(){
return exec(stmt); public Integer handleQueryResult(Statement stmt, ResultSet result) {
} try {
if(stmt != null)
/** return stmt.getUpdateCount();
* Executes an query and cleans up after itself. else
* return -1;
* @param stmt is the query } catch (SQLException e) {
* @return update count or -1 if the query is not an update query logger.log(Level.WARNING, null, e);
*/ }
public static int exec(PreparedStatement stmt) throws SQLException { return -1;
Integer ret = exec(stmt, new SQLResultHandler<Integer>(){ }
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 <T>
* @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> T exec(String query, SQLResultHandler<T> handler) throws SQLException {
PreparedStatement stmt = getPreparedStatement( query );
return exec(stmt, handler);
}
/** if(ret != null)
* Executes a query and cleans up after itself. return ret;
* return -1;
* @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> T exec(PreparedStatement stmt, SQLResultHandler<T> handler) throws SQLException{
try{
// Execute
boolean isResultSet = stmt.execute();
// Handle result /**
if( handler != null ){ * Executes an query and cleans up after itself.
ResultSet result = null; *
try{ * @param <T>
if(isResultSet){ * @param query is the query
result = stmt.getResultSet(); * @param handler is the result handler
return handler.handleQueryResult(stmt, result); * @return update count or -1 if the query is not an update query
} */
else public <T> T exec(String query, SQLResultHandler<T> handler) throws SQLException {
return null; PreparedStatement stmt = getPreparedStatement( query );
}catch(SQLException e){ return exec(stmt, handler);
logger.log(Level.WARNING, null, e); }
}finally{
if(result != null){ /**
try { * Executes a query and cleans up after itself.
result.close(); *
} catch (SQLException e) { * @param stmt is the query to run
logger.log(Level.WARNING, null, e); * @param handler is the result handler that will be called with the output of the execution
} * @return the object from the handler
result = null; */
} public static <T> T exec(PreparedStatement stmt, SQLResultHandler<T> handler) throws SQLException {
} try{
} // Execute
}catch(SQLException e){ boolean isResultSet = stmt.execute();
logger.log(Level.WARNING, null, e);
// Cleanup // Handle result
} finally { if( handler != null ){
if (stmt != null) { ResultSet result = null;
try { try{
stmt.close(); if(isResultSet){
} catch (SQLException e) { result = stmt.getResultSet();
logger.log(Level.WARNING, null, e); return handler.handleQueryResult(stmt, result);
} }
stmt = null; else
} return null;
} }catch(SQLException e){
return null; 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. * Executes an query and cleans up after itself.
@ -306,60 +299,60 @@ public class DBConnection implements Closeable{
return new int[0]; return new int[0];
} }
/** /**
* Sets the pool that this connection belongs to * Sets the pool that this connection belongs to
* *
* @param pool is the pool * @param pool is the pool
*/ */
protected void setPool(DBConnectionPool pool){ protected void setPool(DBConnectionPool pool){
if( pool != null ) if( pool != null )
pool.removeConnection(this); pool.removeConnection(this);
this.pool = pool; this.pool = pool;
} }
/** /**
* Checks if the DB Connection is valid and functioning * Checks if the DB Connection is valid and functioning
* *
* @return true or false depending on the validity of the connection * @return true or false depending on the validity of the connection
*/ */
public boolean valid(){ public boolean valid(){
try { try {
conn.getMetaData(); conn.getMetaData();
return !conn.isClosed(); return !conn.isClosed();
}catch (Exception e) { }catch (Exception e) {
return false; return false;
} }
} }
/** /**
* Disconnects from the database or releases the connection back to the pool * Disconnects from the database or releases the connection back to the pool
*/ */
public void close(){ public void close(){
if(pool!=null){ if(pool != null){
pool.releaseConnection(this); pool.releaseConnection(this);
conn = null; conn = null;
} }
else{ else{
forceClose(); forceClose();
} }
} }
/** /**
* Disconnects from the database * Disconnects from the database
*/ */
public void forceClose(){ public void forceClose(){
if (conn != null) { if (conn != null) {
try { try {
if( !conn.isClosed() ) if( !conn.isClosed() )
conn.close(); conn.close();
} catch (SQLException e) { } catch (SQLException e) {
logger.log(Level.WARNING, null, e); logger.log(Level.WARNING, null, e);
} }
conn = null; conn = null;
} }
} }
public boolean equals(Object o){ public boolean equals(Object o){
return conn.equals(o); return conn.equals(o);
} }
} }

View file

@ -64,85 +64,85 @@ import java.util.logging.Logger;
* @author Ziver * @author Ziver
*/ */
public abstract class DBBean { 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 * Sets the name of the table in the database
*/ */
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE) @Target(ElementType.TYPE)
public @interface DBTable { public @interface DBTable {
/** This is the name of the table, SQL rules apply should not contain any strange characters or spaces **/ /** This is the name of the table, SQL rules apply should not contain any strange characters or spaces **/
String value(); 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 **/ /** 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"; String idColumn() default "id";
/** Sets if the fields in the super classes is also part of the bean **/ /** Sets if the fields in the super classes is also part of the bean **/
boolean superBean() default false; boolean superBean() default false;
} }
/** /**
* Can be used if the column name is different from the field name. * Can be used if the column name is different from the field name.
*/ */
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD) @Target(ElementType.FIELD)
public @interface DBColumn { 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 **/ /** 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(); String value();
} }
/** /**
* Should be used for fields with lists of DBBeans. * Should be used for fields with lists of DBBeans.
*/ */
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD) @Target(ElementType.FIELD)
public @interface DBLinkTable { 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(); String table();
/** The class of the linked bean */ /** The class of the linked bean */
Class<? extends DBBean> beanClass(); Class<? extends DBBean> beanClass();
/** The name of the column that contains the parent beans 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 ""; String idColumn() default "";
} }
/** A unique id of the bean **/ /** A unique id of the bean **/
private Long id; private Long id;
/** This lock is for preventing recursive loops and concurrency when saving */ /** This lock is for preventing recursive loops and concurrency when saving */
protected ReentrantLock saveLock; protected ReentrantLock saveLock;
/** This value is for preventing recursive loops when updating */ /** This value is for preventing recursive loops when updating */
protected ReentrantLock readLock; protected ReentrantLock readLock;
protected DBBean(){ protected DBBean(){
DBBeanConfig.getBeanConfig(this.getClass()); DBBeanConfig.getBeanConfig(this.getClass());
saveLock = new ReentrantLock(); saveLock = new ReentrantLock();
readLock = new ReentrantLock(); readLock = new ReentrantLock();
} }
/** /**
* Saves the bean and all its sub beans to the DB * Saves the bean and all its sub beans to the DB
* *
* @param db is the DBMS connection * @param db is the DBMS connection
*/ */
public void save(DBConnection db) throws SQLException{ public void save(DBConnection db) throws SQLException{
save( db, true ); save( db, true );
} }
/** /**
* Saves the bean to the DB * Saves the bean to the DB
* *
* @param db the DBMS connection * @param db the DBMS connection
* @param recursive if all sub beans should be saved also * @param recursive if all sub beans should be saved also
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public void save(DBConnection db, boolean recursive) throws SQLException{ public void save(DBConnection db, boolean recursive) throws SQLException{
if (saveLock.isHeldByCurrentThread()) // If the current thread already has a lock then this 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 return; // is a recursive call and we do not need to do anything
else if (saveLock.tryLock()) { else if (saveLock.tryLock()) {
Class<? extends DBBean> c = this.getClass(); Class<? extends DBBean> c = this.getClass();
DBBeanConfig config = DBBeanConfig.getBeanConfig(c); DBBeanConfig config = DBBeanConfig.getBeanConfig(c);
try { try {
@ -153,13 +153,13 @@ public abstract class DBBean {
StringBuilder sqlCols = new StringBuilder(); StringBuilder sqlCols = new StringBuilder();
StringBuilder sqlValues = new StringBuilder(); StringBuilder sqlValues = new StringBuilder();
for (DBBeanFieldConfig field : config.getFields()) { for (DBBeanFieldConfig field : config.getFields()) {
if (sqlCols.length() > 0) if (sqlCols.length() > 0)
sqlCols.append(", "); sqlCols.append(", ");
sqlCols.append(field.getName()); sqlCols.append(field.getName());
if (sqlValues.length() > 0) if (sqlValues.length() > 0)
sqlValues.append(", "); sqlValues.append(", ");
sqlValues.append("?"); sqlValues.append("?");
} }
if (config.getFields().size() > 0) { // is there any fields? if (config.getFields().size() > 0) { // is there any fields?
query.append(" (").append(sqlCols).append(")"); query.append(" (").append(sqlCols).append(")");
@ -171,10 +171,10 @@ public abstract class DBBean {
query.append("UPDATE ").append(config.getTableName()); query.append("UPDATE ").append(config.getTableName());
StringBuilder sqlSets = new StringBuilder(); StringBuilder sqlSets = new StringBuilder();
for (DBBeanFieldConfig field : config.getFields()) { for (DBBeanFieldConfig field : config.getFields()) {
if (sqlSets.length() > 0) if (sqlSets.length() > 0)
sqlSets.append(", "); sqlSets.append(", ");
sqlSets.append(field.getName()); sqlSets.append(field.getName());
sqlSets.append("=?"); sqlSets.append("=?");
} }
query.append(" SET ").append(sqlSets); query.append(" SET ").append(sqlSets);
query.append(" WHERE ").append(config.getIdColumnName()).append("=?"); query.append(" WHERE ").append(config.getIdColumnName()).append("=?");
@ -264,11 +264,11 @@ public abstract class DBBean {
saveLock.unlock(); saveLock.unlock();
} }
} else { } 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.lock();
saveLock.unlock(); saveLock.unlock();
} }
} }
/** /**
@ -277,18 +277,18 @@ public abstract class DBBean {
public void delete(DBConnection db) throws SQLException{ public void delete(DBConnection db) throws SQLException{
delete(db, true); 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 * @param recursive if all sub beans should be deleted also
*/ */
public void delete(DBConnection db, boolean recursive) throws SQLException{ public void delete(DBConnection db, boolean recursive) throws SQLException{
Class<? extends DBBean> c = this.getClass(); Class<? extends DBBean> c = this.getClass();
DBBeanConfig config = DBBeanConfig.getBeanConfig( c ); DBBeanConfig config = DBBeanConfig.getBeanConfig( c );
if( this.getId() == null ) if( this.getId() == null )
throw new NullPointerException("ID field is null! (Has the bean been saved?)"); throw new NullPointerException("ID field is null! (Has the bean been saved?)");
// Delete sub beans // Delete sub beans
for (DBBeanSubBeanConfig subBeanField : config.getSubBeans()) { for (DBBeanSubBeanConfig subBeanField : config.getSubBeans()) {
List<DBBean> list = (List<DBBean>) subBeanField.getValue(this); List<DBBean> list = (List<DBBean>) subBeanField.getValue(this);
if (list != null) { if (list != null) {
@ -309,130 +309,130 @@ public abstract class DBBean {
} }
// Delete this bean from DB // Delete this bean from DB
String sql = "DELETE FROM "+config.getTableName()+" WHERE "+config.getIdColumnName()+"=?"; String sql = "DELETE FROM "+config.getTableName()+" WHERE "+config.getIdColumnName()+"=?";
logger.finest("Delete Bean("+c.getName()+", id: "+this.getId()+") query: "+sql); logger.finest("Delete Bean("+c.getName()+", id: "+this.getId()+") query: "+sql);
PreparedStatement stmt = db.getPreparedStatement( sql ); PreparedStatement stmt = db.getPreparedStatement( sql );
stmt.setLong(1, this.getId() ); stmt.setLong(1, this.getId() );
DBConnection.exec(stmt); DBConnection.exec(stmt);
// Clear cache and reset id // Clear cache and reset id
DBBeanCache.remove(this); DBBeanCache.remove(this);
this.id = null; this.id = null;
} }
/**
* Loads all rows from the table into a LinkedList
*
* @param <T> 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 <T extends DBBean> List<T> load(DBConnection db, Class<T> 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<T> 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 <T> 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 extends DBBean> T load(DBConnection db, Class<T> 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<? extends DBBean> 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 * Loads all rows from the table into a LinkedList
*/ *
public final Long getId(){ * @param <T> is the class of the bean
return id; * @param c is the class of the bean
} * @return a LinkedList with all the beans in the DB
*/
public static <T extends DBBean> List<T> load(DBConnection db, Class<T> 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<T> 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 <T> 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 extends DBBean> T load(DBConnection db, Class<T> 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<? extends DBBean> 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){ final void setId(Long id){
this.id = id; this.id = id;
} }
////////////////// EXTENDABLE METHODS ///////////////////////// ////////////////// EXTENDABLE METHODS /////////////////////////
/** /**
* Will be called whenever the bean has been updated from the database. * Will be called whenever the bean has been updated from the database.
*/ */
protected void postUpdateAction(){} protected void postUpdateAction(){}
} }