2015-05-27 13:13:19 +00:00
|
|
|
/*
|
2015-10-01 15:23:40 +00:00
|
|
|
* The MIT License (MIT)
|
|
|
|
|
*
|
|
|
|
|
* Copyright (c) 2015 Ziver Koc
|
2013-05-28 19:29:24 +00:00
|
|
|
*
|
2011-07-13 17:53:17 +00:00
|
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
|
|
|
* of this software and associated documentation files (the "Software"), to deal
|
|
|
|
|
* in the Software without restriction, including without limitation the rights
|
|
|
|
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
|
|
|
* copies of the Software, and to permit persons to whom the Software is
|
|
|
|
|
* furnished to do so, subject to the following conditions:
|
2013-05-28 19:29:24 +00:00
|
|
|
*
|
2011-07-13 17:53:17 +00:00
|
|
|
* The above copyright notice and this permission notice shall be included in
|
|
|
|
|
* all copies or substantial portions of the Software.
|
2013-05-28 19:29:24 +00:00
|
|
|
*
|
2011-07-13 17:53:17 +00:00
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
|
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
|
|
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
|
|
|
* THE SOFTWARE.
|
2015-05-27 13:13:19 +00:00
|
|
|
*/
|
2013-05-28 19:29:24 +00:00
|
|
|
|
2010-08-30 15:23:58 +00:00
|
|
|
package zutil.db.bean;
|
|
|
|
|
|
2015-06-02 15:47:44 +00:00
|
|
|
import zutil.db.DBConnection;
|
|
|
|
|
import zutil.log.LogUtil;
|
|
|
|
|
|
2010-08-30 15:23:58 +00:00
|
|
|
import java.lang.annotation.ElementType;
|
|
|
|
|
import java.lang.annotation.Retention;
|
|
|
|
|
import java.lang.annotation.RetentionPolicy;
|
|
|
|
|
import java.lang.annotation.Target;
|
|
|
|
|
import java.lang.reflect.Field;
|
|
|
|
|
import java.lang.reflect.Modifier;
|
|
|
|
|
import java.math.BigDecimal;
|
|
|
|
|
import java.math.BigInteger;
|
|
|
|
|
import java.sql.PreparedStatement;
|
|
|
|
|
import java.sql.SQLException;
|
2010-11-09 17:17:53 +00:00
|
|
|
import java.sql.Timestamp;
|
2010-08-30 15:23:58 +00:00
|
|
|
import java.util.ArrayList;
|
|
|
|
|
import java.util.HashMap;
|
|
|
|
|
import java.util.List;
|
|
|
|
|
import java.util.NoSuchElementException;
|
2010-11-07 15:40:59 +00:00
|
|
|
import java.util.logging.Level;
|
2010-10-07 11:27:02 +00:00
|
|
|
import java.util.logging.Logger;
|
2010-08-30 15:23:58 +00:00
|
|
|
|
2014-07-01 19:54:30 +00:00
|
|
|
/**
|
|
|
|
|
* The class that extends this will be able to save its state to a database.
|
2010-08-30 15:23:58 +00:00
|
|
|
* Fields that are transient will be ignored, and fields that extend
|
2014-07-01 19:54:30 +00:00
|
|
|
* DBBean will be replaced with the an id which corresponds to the field
|
|
|
|
|
* of that object.
|
2010-08-30 15:23:58 +00:00
|
|
|
*
|
2014-07-01 19:54:30 +00:00
|
|
|
* <XMP>
|
2010-09-04 16:53:44 +00:00
|
|
|
* Supported fields:
|
2010-11-07 15:40:59 +00:00
|
|
|
* *Boolean
|
|
|
|
|
* *Integer
|
|
|
|
|
* *Short
|
|
|
|
|
* *Float
|
|
|
|
|
* *Double
|
|
|
|
|
* *String
|
|
|
|
|
* *Character
|
|
|
|
|
* *DBBean
|
2010-11-09 17:17:53 +00:00
|
|
|
* *java.sql.Timestamp
|
2014-07-01 19:54:30 +00:00
|
|
|
* *List<DBBean>
|
2010-09-04 16:53:44 +00:00
|
|
|
* </XMP>
|
2010-08-30 15:23:58 +00:00
|
|
|
* @author Ziver
|
|
|
|
|
*/
|
|
|
|
|
public abstract class DBBean {
|
2011-03-05 18:53:42 +00:00
|
|
|
private static final Logger logger = LogUtil.getLogger();
|
2010-11-07 15:40:59 +00:00
|
|
|
|
2010-10-07 11:27:02 +00:00
|
|
|
/** The id of the bean **/
|
2010-10-30 13:04:45 +00:00
|
|
|
protected Long id;
|
2010-11-07 15:40:59 +00:00
|
|
|
|
2010-08-30 15:23:58 +00:00
|
|
|
/**
|
|
|
|
|
* Sets the name of the table in the database
|
|
|
|
|
*/
|
|
|
|
|
@Retention(RetentionPolicy.RUNTIME)
|
|
|
|
|
@Target(ElementType.TYPE)
|
|
|
|
|
public @interface DBTable {
|
2011-06-24 23:20:59 +00:00
|
|
|
/** This is the name of the table, SQL rules apply should not contain any strange characters or spaces **/
|
2010-10-07 11:27:02 +00:00
|
|
|
String value();
|
2011-06-24 23:20:59 +00:00
|
|
|
/** 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";
|
2011-03-05 18:53:42 +00:00
|
|
|
/** Sets if the fields in the super classes is also part of the bean **/
|
|
|
|
|
boolean superBean() default false;
|
2010-08-30 15:23:58 +00:00
|
|
|
}
|
2010-10-07 11:27:02 +00:00
|
|
|
|
2010-09-04 16:53:44 +00:00
|
|
|
/**
|
|
|
|
|
* Sets the name of the table that links different DBBeans together
|
|
|
|
|
*/
|
|
|
|
|
@Retention(RetentionPolicy.RUNTIME)
|
|
|
|
|
@Target(ElementType.FIELD)
|
|
|
|
|
public @interface DBLinkTable {
|
2011-06-24 23:20:59 +00:00
|
|
|
/** The name of the Link table, SQL rules apply should not contain any strange characters or spaces */
|
|
|
|
|
String table();
|
2010-10-07 11:27:02 +00:00
|
|
|
/** The class of the linked bean */
|
|
|
|
|
Class<? extends DBBean> beanClass();
|
2011-06-24 23:20:59 +00:00
|
|
|
/** The name of the column that contains the main objects id, SQL rules apply should not contain any strange characters or spaces */
|
2010-11-09 18:58:52 +00:00
|
|
|
String idColumn() default "";
|
2010-09-04 16:53:44 +00:00
|
|
|
}
|
2010-10-07 11:27:02 +00:00
|
|
|
|
2010-08-30 15:23:58 +00:00
|
|
|
/**
|
|
|
|
|
* A Class that contains information about a bean
|
|
|
|
|
*/
|
|
|
|
|
protected static class DBBeanConfig{
|
2011-06-24 23:20:59 +00:00
|
|
|
/** The name of the table in the DB **/
|
2010-08-30 15:23:58 +00:00
|
|
|
protected String tableName;
|
2011-06-24 23:20:59 +00:00
|
|
|
/** The name of the id column **/
|
|
|
|
|
protected String idColumn;
|
|
|
|
|
/** All the fields in the bean **/
|
2010-08-30 15:23:58 +00:00
|
|
|
protected ArrayList<Field> fields;
|
2010-10-07 11:27:02 +00:00
|
|
|
|
2010-08-30 15:23:58 +00:00
|
|
|
protected DBBeanConfig(){
|
|
|
|
|
fields = new ArrayList<Field>();
|
|
|
|
|
}
|
|
|
|
|
}
|
2010-10-07 11:27:02 +00:00
|
|
|
|
2010-09-04 16:53:44 +00:00
|
|
|
/** This is a cache of all the initialized beans */
|
2011-03-05 18:53:42 +00:00
|
|
|
private static HashMap<String,DBBeanConfig> beanConfigs = new HashMap<String,DBBeanConfig>();
|
2010-11-25 22:02:44 +00:00
|
|
|
/** This value is for preventing recursive loops when saving */
|
|
|
|
|
protected boolean processing_save;
|
|
|
|
|
/** This value is for preventing recursive loops when updating */
|
|
|
|
|
protected boolean processing_update;
|
2010-10-07 11:27:02 +00:00
|
|
|
|
2010-08-30 15:23:58 +00:00
|
|
|
protected DBBean(){
|
|
|
|
|
if( !beanConfigs.containsKey( this.getClass() ) )
|
|
|
|
|
initBeanConfig( this.getClass() );
|
2010-11-25 22:02:44 +00:00
|
|
|
processing_save = false;
|
|
|
|
|
processing_update = false;
|
2010-08-30 15:23:58 +00:00
|
|
|
}
|
2010-10-07 11:27:02 +00:00
|
|
|
|
2010-08-30 15:23:58 +00:00
|
|
|
/**
|
|
|
|
|
* @return all the fields except the ID field
|
|
|
|
|
*/
|
|
|
|
|
public static ArrayList<Field> getFields(Class<? extends DBBean> c){
|
2011-03-05 18:53:42 +00:00
|
|
|
if( !beanConfigs.containsKey( c.getName() ) )
|
2010-08-30 15:23:58 +00:00
|
|
|
initBeanConfig( c );
|
2011-03-05 18:53:42 +00:00
|
|
|
return beanConfigs.get( c.getName() ).fields;
|
2010-08-30 15:23:58 +00:00
|
|
|
}
|
2010-10-07 11:27:02 +00:00
|
|
|
|
2010-08-30 15:23:58 +00:00
|
|
|
/**
|
|
|
|
|
* @return the configuration object for the specified class
|
|
|
|
|
*/
|
|
|
|
|
protected static DBBeanConfig getBeanConfig(Class<? extends DBBean> c){
|
2011-03-05 18:53:42 +00:00
|
|
|
if( !beanConfigs.containsKey( c.getName() ) )
|
2010-08-30 15:23:58 +00:00
|
|
|
initBeanConfig( c );
|
2011-03-05 18:53:42 +00:00
|
|
|
return beanConfigs.get( c.getName() );
|
2010-08-30 15:23:58 +00:00
|
|
|
}
|
2010-10-07 11:27:02 +00:00
|
|
|
|
2010-08-30 15:23:58 +00:00
|
|
|
/**
|
|
|
|
|
* Caches the fields
|
|
|
|
|
*/
|
|
|
|
|
private static void initBeanConfig(Class<? extends DBBean> c){
|
2011-03-05 18:53:42 +00:00
|
|
|
logger.fine("Initiating new DBBeanConfig( "+c.getName()+" )");
|
2010-08-30 15:23:58 +00:00
|
|
|
DBBeanConfig config = new DBBeanConfig();
|
|
|
|
|
// Find the table name
|
2011-03-05 18:53:42 +00:00
|
|
|
DBTable tableAnn = c.getAnnotation(DBTable.class);
|
2011-06-24 23:20:59 +00:00
|
|
|
if( tableAnn != null ){
|
|
|
|
|
config.tableName = tableAnn.value();
|
|
|
|
|
config.idColumn = tableAnn.idColumn();
|
|
|
|
|
}
|
|
|
|
|
else{
|
|
|
|
|
config.tableName = c.getSimpleName();
|
|
|
|
|
config.idColumn = "id";
|
|
|
|
|
}
|
2011-03-05 18:53:42 +00:00
|
|
|
// Add the fields in the bean and all the super classes fields
|
|
|
|
|
for(Class<?> cc = c; cc != DBBean.class ;cc = cc.getSuperclass()){
|
|
|
|
|
Field[] fields = cc.getDeclaredFields();
|
|
|
|
|
for( Field field : fields ){
|
|
|
|
|
int mod = field.getModifiers();
|
|
|
|
|
if( !Modifier.isTransient( mod ) &&
|
|
|
|
|
!Modifier.isAbstract( mod ) &&
|
|
|
|
|
!Modifier.isFinal( mod ) &&
|
|
|
|
|
!Modifier.isStatic( mod ) &&
|
|
|
|
|
!Modifier.isInterface( mod ) &&
|
|
|
|
|
!Modifier.isNative( mod ) &&
|
|
|
|
|
!config.fields.contains( field )){
|
|
|
|
|
config.fields.add( field );
|
|
|
|
|
}
|
2010-08-30 15:23:58 +00:00
|
|
|
}
|
2011-03-05 18:53:42 +00:00
|
|
|
if( tableAnn == null || !tableAnn.superBean() )
|
|
|
|
|
break;
|
2010-08-30 15:23:58 +00:00
|
|
|
}
|
2010-10-07 11:27:02 +00:00
|
|
|
|
2011-03-05 18:53:42 +00:00
|
|
|
beanConfigs.put(c.getName(), config);
|
2010-08-30 15:23:58 +00:00
|
|
|
}
|
2010-10-07 11:27:02 +00:00
|
|
|
|
2010-11-09 17:17:53 +00:00
|
|
|
/**
|
|
|
|
|
* Saves the object and all the sub objects to the DB
|
|
|
|
|
*
|
|
|
|
|
* @param db is the DBMS connection
|
|
|
|
|
*/
|
|
|
|
|
public void save(DBConnection db) throws SQLException{
|
|
|
|
|
save( db, true );
|
|
|
|
|
}
|
|
|
|
|
|
2010-08-30 15:23:58 +00:00
|
|
|
/**
|
|
|
|
|
* Saves the Object to the DB
|
2010-11-09 17:17:53 +00:00
|
|
|
*
|
|
|
|
|
* @param db is the DBMS connection
|
|
|
|
|
* @param recursive is if the method should save all sub objects
|
2010-08-30 15:23:58 +00:00
|
|
|
*/
|
2010-09-04 16:53:44 +00:00
|
|
|
@SuppressWarnings("unchecked")
|
2010-11-09 17:17:53 +00:00
|
|
|
public void save(DBConnection db, boolean recursive) throws SQLException{
|
2010-11-25 22:02:44 +00:00
|
|
|
if( processing_save )
|
2010-09-04 16:53:44 +00:00
|
|
|
return;
|
2010-11-25 22:02:44 +00:00
|
|
|
processing_save = true;
|
2010-08-30 15:23:58 +00:00
|
|
|
Class<? extends DBBean> c = this.getClass();
|
2011-03-05 18:53:42 +00:00
|
|
|
DBBeanConfig config = getBeanConfig( c );
|
2010-08-30 15:23:58 +00:00
|
|
|
try {
|
2010-10-30 13:04:45 +00:00
|
|
|
Long id = this.getId();
|
2010-08-30 15:23:58 +00:00
|
|
|
// Generate the SQL
|
|
|
|
|
StringBuilder query = new StringBuilder();
|
2010-10-07 11:27:02 +00:00
|
|
|
if( id == null )
|
|
|
|
|
query.append("INSERT INTO ");
|
|
|
|
|
else query.append("UPDATE ");
|
|
|
|
|
query.append( config.tableName );
|
2010-11-07 15:40:59 +00:00
|
|
|
|
2010-10-07 11:27:02 +00:00
|
|
|
StringBuilder params = new StringBuilder();
|
2010-08-30 15:23:58 +00:00
|
|
|
for( Field field : config.fields ){
|
2010-10-07 11:27:02 +00:00
|
|
|
if( !List.class.isAssignableFrom(field.getType()) ){
|
|
|
|
|
params.append(" ");
|
|
|
|
|
params.append(field.getName());
|
|
|
|
|
params.append("=?,");
|
|
|
|
|
}
|
2010-08-30 15:23:58 +00:00
|
|
|
}
|
2010-10-07 11:27:02 +00:00
|
|
|
if( params.length() > 0 ){
|
|
|
|
|
params.delete( params.length()-1, params.length());
|
|
|
|
|
query.append( " SET" );
|
|
|
|
|
query.append( params );
|
|
|
|
|
if( id != null )
|
2011-06-24 23:20:59 +00:00
|
|
|
query.append(" WHERE ").append(config.idColumn).append("=?");
|
2010-10-07 11:27:02 +00:00
|
|
|
}
|
2010-12-26 18:17:35 +00:00
|
|
|
logger.finest("Save query("+c.getName()+" id:"+this.getId()+"): "+query.toString());
|
2010-10-07 11:27:02 +00:00
|
|
|
PreparedStatement stmt = db.getPreparedStatement( query.toString() );
|
2010-08-30 15:23:58 +00:00
|
|
|
// Put in the variables in the SQL
|
2010-11-01 22:31:53 +00:00
|
|
|
int index = 1;
|
|
|
|
|
for(Field field : config.fields){
|
2010-10-07 11:27:02 +00:00
|
|
|
|
2010-08-30 15:23:58 +00:00
|
|
|
// Another DBBean class
|
2010-09-04 16:53:44 +00:00
|
|
|
if( DBBean.class.isAssignableFrom( field.getType() )){
|
2010-10-27 13:49:46 +00:00
|
|
|
DBBean subobj = (DBBean)getFieldValue(field);
|
2010-10-07 11:27:02 +00:00
|
|
|
if(subobj != null){
|
2010-11-09 17:17:53 +00:00
|
|
|
if( recursive || subobj.getId() == null )
|
|
|
|
|
subobj.save(db);
|
2010-11-01 22:31:53 +00:00
|
|
|
stmt.setObject(index, subobj.getId() );
|
2010-10-07 11:27:02 +00:00
|
|
|
}
|
|
|
|
|
else
|
2010-11-01 22:31:53 +00:00
|
|
|
stmt.setObject(index, null);
|
|
|
|
|
index++;
|
2010-08-30 15:23:58 +00:00
|
|
|
}
|
2010-09-04 16:53:44 +00:00
|
|
|
// A list of DBBeans
|
|
|
|
|
else if( List.class.isAssignableFrom( field.getType() ) &&
|
|
|
|
|
field.getAnnotation( DBLinkTable.class ) != null){
|
2010-11-09 17:17:53 +00:00
|
|
|
// DO NOTING
|
|
|
|
|
}
|
|
|
|
|
// Normal field
|
|
|
|
|
else{
|
|
|
|
|
Object value = getFieldValue(field);
|
|
|
|
|
stmt.setObject(index, value);
|
|
|
|
|
index++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if( id != null )
|
|
|
|
|
stmt.setObject(index, id);
|
|
|
|
|
|
|
|
|
|
// Execute the SQL
|
|
|
|
|
DBConnection.exec(stmt);
|
|
|
|
|
if( id == null )
|
2013-09-07 01:14:18 +00:00
|
|
|
this.id = db.getLastInsertID();
|
2010-11-09 17:17:53 +00:00
|
|
|
|
|
|
|
|
// Save the list, after we get the object id
|
|
|
|
|
for(Field field : config.fields){
|
|
|
|
|
if( List.class.isAssignableFrom( field.getType() ) &&
|
|
|
|
|
field.getAnnotation( DBLinkTable.class ) != null){
|
2010-10-07 11:27:02 +00:00
|
|
|
List<DBBean> list = (List<DBBean>)getFieldValue(field);
|
|
|
|
|
if( list != null ){
|
|
|
|
|
DBLinkTable linkTable = field.getAnnotation( DBLinkTable.class );
|
2011-06-24 23:20:59 +00:00
|
|
|
String subtable = linkTable.table();
|
2010-11-09 18:58:52 +00:00
|
|
|
String idcol = (linkTable.idColumn().isEmpty() ? config.tableName : linkTable.idColumn() );
|
2010-11-09 17:17:53 +00:00
|
|
|
String sub_idcol = "id";
|
2010-11-07 15:40:59 +00:00
|
|
|
|
2010-10-07 11:27:02 +00:00
|
|
|
DBBeanConfig subConfig = null;
|
|
|
|
|
for(DBBean subobj : list){
|
2010-11-09 17:17:53 +00:00
|
|
|
// Save the sub bean
|
|
|
|
|
if( recursive || subobj.getId() == null )
|
|
|
|
|
subobj.save(db);
|
2010-12-20 22:57:17 +00:00
|
|
|
if( subobj.getId() == null ){
|
2010-12-21 21:13:01 +00:00
|
|
|
logger.severe("Unable to save field "+c.getSimpleName()+"."+field.getName()+" with "+subobj.getClass().getSimpleName());
|
2010-12-20 22:57:17 +00:00
|
|
|
continue;
|
|
|
|
|
}
|
2010-11-09 17:17:53 +00:00
|
|
|
// Get the Sub object configuration
|
2011-06-24 23:20:59 +00:00
|
|
|
if(subConfig == null){
|
2011-03-05 18:53:42 +00:00
|
|
|
subConfig = getBeanConfig( subobj.getClass() );
|
2011-06-24 23:20:59 +00:00
|
|
|
sub_idcol = subConfig.idColumn;
|
|
|
|
|
}
|
2010-10-07 11:27:02 +00:00
|
|
|
// Save links in link table
|
2010-12-26 18:17:35 +00:00
|
|
|
String subsql = "";
|
|
|
|
|
if( subtable.equals(subConfig.tableName) )
|
|
|
|
|
subsql = "UPDATE "+subtable+" SET "+idcol+"=? WHERE "+sub_idcol+"=?";
|
|
|
|
|
else
|
|
|
|
|
subsql = "REPLACE INTO "+subtable+" SET "+idcol+"=?, "+sub_idcol+"=?";
|
|
|
|
|
logger.finest("List Save query("+c.getName()+" id:"+subobj.getId()+"): "+subsql);
|
2010-11-09 17:17:53 +00:00
|
|
|
PreparedStatement subStmt = db.getPreparedStatement( subsql );
|
|
|
|
|
subStmt.setLong(1, this.getId() );
|
|
|
|
|
subStmt.setLong(2, subobj.getId() );
|
2010-10-07 11:27:02 +00:00
|
|
|
DBConnection.exec(subStmt);
|
|
|
|
|
}
|
2010-09-04 16:53:44 +00:00
|
|
|
}
|
|
|
|
|
}
|
2010-08-30 15:23:58 +00:00
|
|
|
}
|
|
|
|
|
} catch (SQLException e) {
|
|
|
|
|
throw e;
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
throw new SQLException(e);
|
2010-11-25 22:02:44 +00:00
|
|
|
} finally{
|
|
|
|
|
processing_save = false;
|
|
|
|
|
}
|
2010-08-30 15:23:58 +00:00
|
|
|
}
|
2010-10-07 11:27:02 +00:00
|
|
|
|
2010-08-30 15:23:58 +00:00
|
|
|
/**
|
2010-09-04 16:53:44 +00:00
|
|
|
* Deletes the object from the DB, WARNING will not delete sub beans
|
2010-11-07 15:40:59 +00:00
|
|
|
*
|
|
|
|
|
* @throws SQLException
|
2010-08-30 15:23:58 +00:00
|
|
|
*/
|
2010-11-07 15:40:59 +00:00
|
|
|
public void delete(DBConnection db) throws SQLException{
|
2010-08-30 15:23:58 +00:00
|
|
|
Class<? extends DBBean> c = this.getClass();
|
2011-03-05 18:53:42 +00:00
|
|
|
DBBeanConfig config = getBeanConfig( c );
|
2010-10-30 13:04:45 +00:00
|
|
|
if( this.getId() == null )
|
2010-11-07 15:40:59 +00:00
|
|
|
throw new NoSuchElementException("ID field is null( Has the bean been saved?)!");
|
2010-10-07 11:27:02 +00:00
|
|
|
|
2011-06-24 23:20:59 +00:00
|
|
|
String sql = "DELETE FROM "+config.tableName+" WHERE "+config.idColumn+"=?";
|
2010-12-26 18:17:35 +00:00
|
|
|
logger.fine("Delete query("+c.getName()+" id:"+this.getId()+"): "+sql);
|
2010-11-07 15:40:59 +00:00
|
|
|
PreparedStatement stmt = db.getPreparedStatement( sql );
|
|
|
|
|
// Put in the variables in the SQL
|
|
|
|
|
stmt.setObject(1, this.getId() );
|
|
|
|
|
|
|
|
|
|
// Execute the SQL
|
|
|
|
|
DBConnection.exec(stmt);
|
2010-12-21 21:13:01 +00:00
|
|
|
this.id = null;
|
2010-08-30 15:23:58 +00:00
|
|
|
}
|
2010-10-07 11:27:02 +00:00
|
|
|
|
2010-08-30 15:23:58 +00:00
|
|
|
/**
|
2014-07-01 19:54:30 +00:00
|
|
|
* Loads all rows from the table into a LinkedList
|
2010-08-30 15:23:58 +00:00
|
|
|
*
|
|
|
|
|
* @param <T> is the class of the bean
|
|
|
|
|
* @param c is the class of the bean
|
2014-07-01 19:54:30 +00:00
|
|
|
* @return a LinkedList with all the beans in the DB
|
2010-08-30 15:23:58 +00:00
|
|
|
*/
|
2010-09-04 16:53:44 +00:00
|
|
|
public static <T extends DBBean> List<T> load(DBConnection db, Class<T> c) throws SQLException {
|
2010-08-30 15:23:58 +00:00
|
|
|
// Initiate a BeanConfig if there is non
|
2011-03-05 18:53:42 +00:00
|
|
|
DBBeanConfig config = getBeanConfig( c );
|
2010-08-30 15:23:58 +00:00
|
|
|
// Generate query
|
2010-10-07 11:27:02 +00:00
|
|
|
String sql = "SELECT * FROM "+config.tableName;
|
2010-12-26 18:17:35 +00:00
|
|
|
logger.fine("Load All query("+c.getName()+"): "+sql);
|
2010-10-07 11:27:02 +00:00
|
|
|
PreparedStatement stmt = db.getPreparedStatement( sql );
|
2010-08-30 15:23:58 +00:00
|
|
|
// Run query
|
2010-09-04 16:53:44 +00:00
|
|
|
List<T> list = DBConnection.exec(stmt, DBBeanSQLResultHandler.createList(c, db) );
|
2010-08-30 15:23:58 +00:00
|
|
|
return list;
|
|
|
|
|
}
|
2010-10-07 11:27:02 +00:00
|
|
|
|
2010-08-30 15:23:58 +00:00
|
|
|
/**
|
2014-07-01 19:54:30 +00:00
|
|
|
* Loads a specific instance of the bean from the table with the specific id
|
2010-08-30 15:23:58 +00:00
|
|
|
*
|
|
|
|
|
* @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
|
2014-07-01 19:54:30 +00:00
|
|
|
* @return a DBBean Object with the specific id or null if the id was not found
|
2010-08-30 15:23:58 +00:00
|
|
|
*/
|
2010-12-26 18:17:35 +00:00
|
|
|
public static <T extends DBBean> T load(DBConnection db, Class<T> c, long id) throws SQLException {
|
2010-08-30 15:23:58 +00:00
|
|
|
// Initiate a BeanConfig if there is non
|
2011-03-05 18:53:42 +00:00
|
|
|
DBBeanConfig config = getBeanConfig( c );
|
2010-08-30 15:23:58 +00:00
|
|
|
// Generate query
|
2011-06-24 23:20:59 +00:00
|
|
|
String sql = "SELECT * FROM "+config.tableName+" WHERE "+config.idColumn+"=? LIMIT 1";
|
2010-12-26 18:17:35 +00:00
|
|
|
logger.fine("Load query("+c.getName()+" id:"+id+"): "+sql);
|
2010-12-21 21:13:01 +00:00
|
|
|
PreparedStatement stmt = db.getPreparedStatement( sql );
|
2010-10-30 13:04:45 +00:00
|
|
|
stmt.setObject(1, id );
|
2010-08-30 15:23:58 +00:00
|
|
|
// Run query
|
2010-09-04 16:53:44 +00:00
|
|
|
T obj = DBConnection.exec(stmt, DBBeanSQLResultHandler.create(c, db) );
|
2010-08-30 15:23:58 +00:00
|
|
|
return obj;
|
|
|
|
|
}
|
2010-10-07 11:27:02 +00:00
|
|
|
|
2010-08-30 15:23:58 +00:00
|
|
|
/**
|
2010-11-01 22:31:53 +00:00
|
|
|
* Creates a specific table for the given Bean,
|
|
|
|
|
* WARNING: Experimental
|
2010-08-30 15:23:58 +00:00
|
|
|
*/
|
|
|
|
|
public static void create(DBConnection sql, Class<? extends DBBean> c) throws SQLException{
|
2011-03-05 18:53:42 +00:00
|
|
|
DBBeanConfig config = getBeanConfig( c );
|
2010-08-30 15:23:58 +00:00
|
|
|
|
|
|
|
|
// Generate the SQL
|
|
|
|
|
StringBuilder query = new StringBuilder();
|
2010-10-07 11:27:02 +00:00
|
|
|
query.append("CREATE TABLE "+config.tableName+" ( ");
|
|
|
|
|
|
2010-10-30 13:04:45 +00:00
|
|
|
// ID
|
2011-06-24 23:20:59 +00:00
|
|
|
query.append(" ").append(config.idColumn).append(" ");
|
2010-10-30 13:04:45 +00:00
|
|
|
query.append( classToDBName( Long.class ) );
|
2010-11-01 22:31:53 +00:00
|
|
|
query.append(" PRIMARY KEY AUTO_INCREMENT, ");
|
2010-11-07 15:40:59 +00:00
|
|
|
|
2010-08-30 15:23:58 +00:00
|
|
|
for( Field field : config.fields ){
|
|
|
|
|
query.append(" ");
|
|
|
|
|
query.append( field.getName() );
|
|
|
|
|
query.append( classToDBName(c) );
|
|
|
|
|
query.append(", ");
|
|
|
|
|
}
|
|
|
|
|
query.delete( query.length()-2, query.length());
|
|
|
|
|
query.append(")");
|
2010-12-26 18:17:35 +00:00
|
|
|
logger.fine("Create query("+c.getName()+"): "+sql.toString());
|
2010-08-30 15:23:58 +00:00
|
|
|
PreparedStatement stmt = sql.getPreparedStatement( sql.toString() );
|
2010-10-07 11:27:02 +00:00
|
|
|
|
2010-08-30 15:23:58 +00:00
|
|
|
// Execute the SQL
|
|
|
|
|
DBConnection.exec(stmt);
|
|
|
|
|
}
|
2010-10-07 11:27:02 +00:00
|
|
|
|
2010-08-30 15:23:58 +00:00
|
|
|
private static String classToDBName(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)";
|
2010-11-09 17:17:53 +00:00
|
|
|
else if(c == Timestamp.class) return "DATETIME";
|
2010-11-01 22:31:53 +00:00
|
|
|
else if(DBBean.class.isAssignableFrom(c))
|
2010-11-07 15:40:59 +00:00
|
|
|
return classToDBName(Long.class);
|
2010-08-30 15:23:58 +00:00
|
|
|
return null;
|
|
|
|
|
}
|
2010-10-07 11:27:02 +00:00
|
|
|
|
2010-08-30 15:23:58 +00:00
|
|
|
/**
|
|
|
|
|
* This is a workaround if the field is not visible to other classes
|
|
|
|
|
*
|
|
|
|
|
* @param field is the field
|
|
|
|
|
* @return the value of the field
|
|
|
|
|
*/
|
|
|
|
|
protected Object getFieldValue(Field field){
|
|
|
|
|
try {
|
2011-09-19 18:27:37 +00:00
|
|
|
if( !Modifier.isPublic( field.getModifiers()))
|
|
|
|
|
field.setAccessible(true);
|
|
|
|
|
|
2010-08-30 15:23:58 +00:00
|
|
|
return field.get(this);
|
|
|
|
|
} catch (Exception e) {
|
2010-11-07 15:40:59 +00:00
|
|
|
logger.log(Level.WARNING, e.getMessage(), e);
|
2010-08-30 15:23:58 +00:00
|
|
|
}
|
|
|
|
|
return null;
|
|
|
|
|
}
|
2010-10-07 11:27:02 +00:00
|
|
|
|
2010-08-30 15:23:58 +00:00
|
|
|
/**
|
|
|
|
|
* This is a workaround if the field is not visible to other classes
|
|
|
|
|
*
|
|
|
|
|
* @param field is the field
|
2014-10-07 15:26:51 +00:00
|
|
|
* @return the value of the field
|
2010-08-30 15:23:58 +00:00
|
|
|
*/
|
|
|
|
|
protected void setFieldValue(Field field, Object o){
|
|
|
|
|
try {
|
2011-06-24 23:20:59 +00:00
|
|
|
if( !Modifier.isPublic( field.getModifiers()))
|
|
|
|
|
field.setAccessible(true);
|
2014-10-07 15:26:51 +00:00
|
|
|
|
2015-12-12 00:25:17 +01:00
|
|
|
// Set basic data type
|
2010-11-07 15:40:59 +00:00
|
|
|
if( o == null && !Object.class.isAssignableFrom( field.getType() ) ){
|
|
|
|
|
if( field.getType() == Integer.TYPE ) field.setInt(this, 0);
|
|
|
|
|
else if( field.getType() == Character.TYPE )field.setChar(this, (char) 0);
|
|
|
|
|
else if( field.getType() == Byte.TYPE ) field.setByte(this, (byte) 0);
|
|
|
|
|
else if( field.getType() == Short.TYPE ) field.setShort(this, (short) 0);
|
|
|
|
|
else if( field.getType() == Long.TYPE ) field.setLong(this, 0l);
|
|
|
|
|
else if( field.getType() == Float.TYPE ) field.setFloat(this, 0f);
|
|
|
|
|
else if( field.getType() == Double.TYPE ) field.setDouble(this, 0d);
|
|
|
|
|
else if( field.getType() == Boolean.TYPE ) field.setBoolean(this, false);
|
|
|
|
|
}
|
2015-12-12 00:25:17 +01:00
|
|
|
else {
|
|
|
|
|
// Some special cases
|
|
|
|
|
if(field.getType() == Boolean.TYPE && o instanceof Integer)
|
|
|
|
|
field.setBoolean(this, ((Integer)o) > 0 ); // Convert an Integer to boolean
|
|
|
|
|
else
|
|
|
|
|
field.set(this, o);
|
|
|
|
|
}
|
2010-08-30 15:23:58 +00:00
|
|
|
} catch (Exception e) {
|
2010-11-09 17:17:53 +00:00
|
|
|
logger.log(Level.SEVERE, e.getMessage(), e);
|
2010-08-30 15:23:58 +00:00
|
|
|
}
|
|
|
|
|
}
|
2010-11-07 15:40:59 +00:00
|
|
|
|
2010-10-07 11:27:02 +00:00
|
|
|
/**
|
|
|
|
|
* @return the object id or null if the bean has not bean saved yet
|
|
|
|
|
*/
|
|
|
|
|
public Long getId(){
|
|
|
|
|
return id;
|
|
|
|
|
}
|
2011-06-24 23:20:59 +00:00
|
|
|
|
2012-02-05 21:31:22 +00:00
|
|
|
/**
|
|
|
|
|
* This function cancels the internal cache garbage collector in DBBean
|
|
|
|
|
*/
|
|
|
|
|
public static void cancelGBC(){
|
|
|
|
|
DBBeanSQLResultHandler.cancelGBC();
|
|
|
|
|
}
|
|
|
|
|
|
2011-06-24 23:20:59 +00:00
|
|
|
/**
|
|
|
|
|
* Will be called whenever the bean has been updated from the database.
|
|
|
|
|
*/
|
|
|
|
|
protected void updatePerformed(){}
|
2010-08-30 15:23:58 +00:00
|
|
|
}
|