fixed last inserted id issue
This commit is contained in:
parent
86ce0990c6
commit
c5c135320f
2 changed files with 452 additions and 459 deletions
|
|
@ -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{
|
public enum DBMS{
|
||||||
MySQL,
|
MySQL,
|
||||||
SQLite
|
SQLite
|
||||||
}
|
|
||||||
|
|
||||||
// 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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
// 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
|
* Creates an Connection from JNDI
|
||||||
*
|
*
|
||||||
* @param dbms is the DB type
|
* @param jndi the name of the connection, e.g. "jdbc/mysql"
|
||||||
* @param db is the database to connect to
|
*/
|
||||||
*/
|
public DBConnection(String jndi) throws NamingException, SQLException{
|
||||||
public DBConnection(DBMS dbms, String db) throws Exception{
|
InitialContext ctx = new InitialContext();
|
||||||
String dbms_name = initDriver(dbms);
|
DataSource ds = (DataSource)ctx.lookup("java:comp/env/"+jndi);
|
||||||
conn = DriverManager.getConnection ("jdbc:"+dbms_name+":"+db);
|
this.conn = ds.getConnection();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the underlying connection
|
* Creates an Connection to a MySQL server
|
||||||
*/
|
*
|
||||||
public Connection getConnection(){
|
* @param url is the URL of the MySQL server
|
||||||
return conn;
|
* @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);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initiates the DB driver and returns its protocol name.
|
* Creates an Connection to a DB server
|
||||||
*
|
*
|
||||||
* @param db is the DB type
|
* @param dbms is the DB type
|
||||||
* @return the protocol name of the DBMS
|
* @param url is the URL of the MySQL server
|
||||||
*/
|
* @param db is the database to connect to
|
||||||
public static String initDriver(DBMS db) throws InstantiationException, IllegalAccessException, ClassNotFoundException{
|
* @param user is the user name
|
||||||
switch(db){
|
* @param password is the password
|
||||||
case MySQL:
|
*/
|
||||||
Class.forName("com.mysql.jdbc.Driver").newInstance();
|
public DBConnection(DBMS dbms, String url, String db, String user, String password) throws Exception{
|
||||||
DriverManager.setLoginTimeout(10);
|
String dbms_name = initDriver(dbms);
|
||||||
return "mysql";
|
conn = DriverManager.getConnection ("jdbc:"+dbms_name+"://"+url+"/"+db, user, password);
|
||||||
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 file
|
||||||
*/
|
*
|
||||||
public long getLastInsertID(){
|
* @param dbms is the DB type
|
||||||
try{
|
* @param db is the database to connect to
|
||||||
return exec("SELECT LAST_INSERT_ID()", new SimpleSQLResult<Long>());
|
*/
|
||||||
}catch(SQLException e){
|
public DBConnection(DBMS dbms, String db) throws Exception{
|
||||||
logger.log(Level.WARNING, null, e);
|
String dbms_name = initDriver(dbms);
|
||||||
}
|
conn = DriverManager.getConnection ("jdbc:"+dbms_name+":"+db);
|
||||||
return -1;
|
}
|
||||||
}
|
|
||||||
|
/**
|
||||||
|
* @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();
|
||||||
|
else
|
||||||
|
return -1;
|
||||||
|
} catch (SQLException e) {
|
||||||
|
logger.log(Level.WARNING, null, e);
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
/**
|
if(ret != null)
|
||||||
* Executes an query and cleans up after itself.
|
return ret;
|
||||||
*
|
return -1;
|
||||||
* @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<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;
|
* Executes an query and cleans up after itself.
|
||||||
return -1;
|
*
|
||||||
}
|
* @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);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Executes an query and cleans up after itself.
|
* Executes a query and cleans up after itself.
|
||||||
*
|
*
|
||||||
* @param <T>
|
* @param stmt is the query to run
|
||||||
* @param query is the query
|
* @param handler is the result handler that will be called with the output of the execution
|
||||||
* @param handler is the result handler
|
* @return the object from the handler
|
||||||
* @return update count or -1 if the query is not an update query
|
*/
|
||||||
*/
|
public static <T> T exec(PreparedStatement stmt, SQLResultHandler<T> handler) throws SQLException {
|
||||||
public <T> T exec(String query, SQLResultHandler<T> handler) throws SQLException {
|
try{
|
||||||
PreparedStatement stmt = getPreparedStatement( query );
|
// Execute
|
||||||
return exec(stmt, handler);
|
boolean isResultSet = stmt.execute();
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
// Handle result
|
||||||
* Executes a query and cleans up after itself.
|
if( handler != null ){
|
||||||
*
|
ResultSet result = null;
|
||||||
* @param stmt is the query to run
|
try{
|
||||||
* @param handler is the result handler that will be called with the output of the execution
|
if(isResultSet){
|
||||||
* @return the object from the handler
|
result = stmt.getResultSet();
|
||||||
*/
|
return handler.handleQueryResult(stmt, result);
|
||||||
public static <T> T exec(PreparedStatement stmt, SQLResultHandler<T> handler) throws SQLException{
|
}
|
||||||
try{
|
else
|
||||||
// Execute
|
return null;
|
||||||
boolean isResultSet = stmt.execute();
|
}catch(SQLException e){
|
||||||
|
logger.log(Level.WARNING, null, e);
|
||||||
// Handle result
|
}finally{
|
||||||
if( handler != null ){
|
if(result != null){
|
||||||
ResultSet result = null;
|
try {
|
||||||
try{
|
result.close();
|
||||||
if(isResultSet){
|
} catch (SQLException e) {
|
||||||
result = stmt.getResultSet();
|
logger.log(Level.WARNING, null, e);
|
||||||
return handler.handleQueryResult(stmt, result);
|
}
|
||||||
}
|
result = null;
|
||||||
else
|
}
|
||||||
return null;
|
}
|
||||||
}catch(SQLException e){
|
}
|
||||||
logger.log(Level.WARNING, null, e);
|
}catch(SQLException e){
|
||||||
}finally{
|
logger.log(Level.WARNING, null, e);
|
||||||
if(result != null){
|
// Cleanup
|
||||||
try {
|
} finally {
|
||||||
result.close();
|
if (stmt != null) {
|
||||||
} catch (SQLException e) {
|
try {
|
||||||
logger.log(Level.WARNING, null, e);
|
stmt.close();
|
||||||
}
|
} catch (SQLException e) {
|
||||||
result = null;
|
logger.log(Level.WARNING, null, e);
|
||||||
}
|
}
|
||||||
}
|
stmt = null;
|
||||||
}
|
}
|
||||||
}catch(SQLException e){
|
}
|
||||||
logger.log(Level.WARNING, null, e);
|
return null;
|
||||||
// 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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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,119 +309,119 @@ 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;
|
||||||
|
|
@ -431,8 +431,8 @@ public abstract class DBBean {
|
||||||
|
|
||||||
////////////////// 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(){}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue