Index: topia/src/java/org/codelutin/topia/persistence/PersistenceStorageJDBCMultiTable.java diff -u topia/src/java/org/codelutin/topia/persistence/PersistenceStorageJDBCMultiTable.java:1.2 topia/src/java/org/codelutin/topia/persistence/PersistenceStorageJDBCMultiTable.java:1.3 --- topia/src/java/org/codelutin/topia/persistence/PersistenceStorageJDBCMultiTable.java:1.2 Fri Aug 26 17:53:35 2005 +++ topia/src/java/org/codelutin/topia/persistence/PersistenceStorageJDBCMultiTable.java Tue Aug 30 13:19:53 2005 @@ -23,9 +23,9 @@ * Created: 20 juillet 2005 15:25:06 CEST * * @author Benjamin POUSSIN - * @version $Revision: 1.2 $ + * @version $Revision: 1.3 $ * - * Last update: $Date: 2005/08/26 17:53:35 $ + * Last update: $Date: 2005/08/30 13:19:53 $ * by : $Author: bpoussin $ */ @@ -48,6 +48,7 @@ import java.util.Arrays; import java.util.Collection; import java.util.HashMap; +import java.util.IdentityHashMap; import java.util.List; import java.util.Properties; import org.apache.commons.beanutils.MethodUtils; @@ -55,6 +56,7 @@ import org.apache.commons.dbcp.DriverManagerConnectionFactory; import org.apache.commons.dbcp.PoolableConnectionFactory; import org.apache.commons.dbcp.PoolingDriver; +import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.commons.pool.impl.GenericObjectPool; @@ -71,6 +73,7 @@ import org.codelutin.topia.TopiaNotFoundException; import org.codelutin.topia.TopiaQuery; import org.codelutin.topia.Util; +import org.codelutin.util.CallAnalyse; /** * Storage implante sur JDBC. @@ -114,6 +117,7 @@ static private final String SQL_DROP_TABLE = "SQL_DROP_TABLE"; static private final String SQL_GET_TABLE_NAME = "SQL_GET_TABLE_NAME"; static private final String SQL_GET_CHILD = "SQL_GET_CHILD"; + static private final String SQL_COPY_DATA = "SQL_COPY_DATA"; static private final String SQL_TABLE_EXISTS = "SQL_TABLE_EXISTS"; @@ -126,6 +130,7 @@ static private final String SQL_REMOVE_DATA = "SQL_REMOVE_DATA"; /** retourne tous les id des objets existant non delete */ static private final String SQL_GET_ALL_ID = "SQL_GET_ALL_ID"; + static private final String SQL_GET_LONGDATE = "SQL_GET_LONGDATE"; static private final String SQL_INSERT_DATA = "SQL_INSERT_DATA"; static private final String SQL_LOAD_DATA = "SQL_LOAD_DATA"; static private final String SQL_UPDATE_DATA = "SQL_UPDATE_DATA"; @@ -215,11 +220,28 @@ SQL_DEFAULT.put(SQL_GET_ALL_ID, "SELECT DISTINCT(topia_id) FROM {0} WHERE (topia_longdate in (" + Util.SQL_IDS_KEY + ") OR (topia_longdate>0 AND topia_longdate<=?)) AND topia_id NOT IN (SELECT topia_id FROM {0} WHERE topia_isDeleted=true AND (topia_longdate in (" + Util.SQL_IDS_KEY + ") OR (topia_longdate>0 AND topia_longdate<=?)))"); + // Retourne la date de la derniere version valide de l'objet + // {0} de nom de la table + // SQL_IDS_KEY les ids de la transaction et des sous-transactions + // ?1 le topia_id + // ?1 le topia_id + // ?2 le topia_id + // ?3 l'id de la transaction en abs + SQL_DEFAULT.put(SQL_GET_LONGDATE, + "SELECT topia_longdate, topia_isDeleted from {0} where topia_id=? and topia_longdate=(SELECT min(topia_longdate) as topia_longdate from {0} where topia_id=? and abs(topia_longdate) = (SELECT max(abs(topia_longdate)) from {0} where topia_id=? and topia_longdate in (" + Util.SQL_IDS_KEY + ") or (topia_longdate>0 and topia_longdate <= ?)))"); + // {0} le nom de la table // {1} le nom des champs a inserer (commence par une ',') // {2} la valeur des champs a inserer (commence par une ',') SQL_DEFAULT.put(SQL_INSERT_DATA, "INSERT INTO {0} (topia_id, topia_longdate, topia_class, topia_isNew, topia_isDeleted {1}) VALUES (?, ?, ?, ?, ? {2})"); + // {0} le nom de la table + // {1} le nom des champs a inserer (commence par une ',') + // {2} la valeur du topia_longdate a inserer + // ?1 l'id de l'objet a copier + // ?2 le topia_longdate de l'obbjet a copier + SQL_DEFAULT.put(SQL_COPY_DATA, + "INSERT INTO {0} (topia_id, topia_longdate, topia_class, topia_isNew, topia_isDeleted {1}) SELECT topia_id, {2}, topia_class, topia_isNew, topia_isDeleted {1} FROM {0} as t WHERE topia_id=? AND topia_longdate=?"); SQL_DEFAULT.put(SQL_INSERT_MAPPING, "INSERT INTO topia_mapping_table VALUES (?, ?, ?)"); SQL_DEFAULT.put(SQL_INSERT_HERITAGE, @@ -270,67 +292,89 @@ protected Properties properties = null; protected DriverManagerConnectionFactory connectionPool = null; protected HashMap childCache = new HashMap(); + protected IdentityHashMap tableNameCache = new IdentityHashMap(); public PersistenceStorageJDBCMultiTable(Properties properties) throws TopiaException { - this.properties = properties; - String driver = properties.getProperty(TopiaConst.PERSISTENCE_STORAGE_JDBC_DRIVER); - String url = properties.getProperty(TopiaConst.PERSISTENCE_STORAGE_JDBC_URL); - String login = properties.getProperty(TopiaConst.PERSISTENCE_STORAGE_JDBC_LOGIN); - String password = properties.getProperty(TopiaConst.PERSISTENCE_STORAGE_JDBC_PASSWORD); - - if(driver.indexOf("mysql") != -1){ - SQL = SQL_MYSQL; - } else if(driver.indexOf("mckoi") != -1){ - SQL = SQL_MCKOI; - } else if(driver.indexOf("oracle") != -1){ - SQL = SQL_ORACLE; - } else if(driver.indexOf("derby") != -1){ - SQL = SQL_DERBY; - } else { - SQL = SQL_POSTGRESQL; - } - - Util.getClazz(driver); - - - GenericObjectPool connectionPool = new GenericObjectPool(null); - ConnectionFactory connectionFactory = - new DriverManagerConnectionFactory(url, login, password); - StackKeyedObjectPoolFactory statementPool = - new StackKeyedObjectPoolFactory(); - PoolableConnectionFactory poolableConnectionFactory = - new PoolableConnectionFactory(connectionFactory, connectionPool, - statementPool, null, false, false); - PoolingDriver poolDriver = new PoolingDriver(); - poolDriver.registerPool("topia",connectionPool); - - try{ - checkManagementTable(); - }catch(SQLException eee){ - throw new TopiaPersistenceException("Erreur durant la creation des tables", eee); - } - try{ - checkOldTransaction(); - }catch(SQLException eee){ - throw new TopiaPersistenceException("Erreur durant la suppression des anciennes transactions", eee); - } - try{ - checkSchemaVersion(); - }catch(SQLException eee){ - throw new TopiaPersistenceException("Erreur durant la converion de schema des données", eee); + try{ + CallAnalyse.enter(PersistenceStorageJDBCMultiTable.class.getName() + ".PersistenceStorageJDBCMultiTable"); + + this.properties = properties; + String driver = properties.getProperty(TopiaConst.PERSISTENCE_STORAGE_JDBC_DRIVER); + String url = properties.getProperty(TopiaConst.PERSISTENCE_STORAGE_JDBC_URL); + String login = properties.getProperty(TopiaConst.PERSISTENCE_STORAGE_JDBC_LOGIN); + String password = properties.getProperty(TopiaConst.PERSISTENCE_STORAGE_JDBC_PASSWORD); + + if(driver.indexOf("mysql") != -1){ + SQL = SQL_MYSQL; + } else if(driver.indexOf("mckoi") != -1){ + SQL = SQL_MCKOI; + } else if(driver.indexOf("oracle") != -1){ + SQL = SQL_ORACLE; + } else if(driver.indexOf("derby") != -1){ + SQL = SQL_DERBY; + } else { + SQL = SQL_POSTGRESQL; + } + + Util.getClazz(driver); + + + GenericObjectPool connectionPool = new GenericObjectPool(null); + ConnectionFactory connectionFactory = + new DriverManagerConnectionFactory(url, login, password); + StackKeyedObjectPoolFactory statementPool = + new StackKeyedObjectPoolFactory(); + PoolableConnectionFactory poolableConnectionFactory = + new PoolableConnectionFactory(connectionFactory, connectionPool, + statementPool, null, false, false); + PoolingDriver poolDriver = new PoolingDriver(); + poolDriver.registerPool("topia",connectionPool); + + try{ + checkManagementTable(); + }catch(SQLException eee){ + throw new TopiaPersistenceException("Erreur durant la creation des tables", eee); + } + try{ + checkOldTransaction(); + }catch(SQLException eee){ + throw new TopiaPersistenceException("Erreur durant la suppression des anciennes transactions", eee); + } + try{ + checkSchemaVersion(); + }catch(SQLException eee){ + throw new TopiaPersistenceException("Erreur durant la converion de schema des données", eee); + } + } finally { + CallAnalyse.exit(PersistenceStorageJDBCMultiTable.class.getName() + ".PersistenceStorageJDBCMultiTable"); } } protected String objectToDatabaseFieldName(String f){ - return "field_" + f; + try{ + CallAnalyse.enter(PersistenceStorageJDBCMultiTable.class.getName() + ".objectToDatabaseFieldName"); + return "field_" + f; + } finally { + CallAnalyse.exit(PersistenceStorageJDBCMultiTable.class.getName() + ".objectToDatabaseFieldName"); + } } protected String databaseToObjectFieldName(String f){ - return f.substring("field_".length()); + try{ + CallAnalyse.enter(PersistenceStorageJDBCMultiTable.class.getName() + ".databaseToObjectFieldName"); + return f.substring("field_".length()); + } finally { + CallAnalyse.exit(PersistenceStorageJDBCMultiTable.class.getName() + ".databaseToObjectFieldName"); + } } protected Connection getConnection() throws SQLException { - return DriverManager.getConnection("jdbc:apache:commons:dbcp:topia"); + try{ + CallAnalyse.enter(PersistenceStorageJDBCMultiTable.class.getName() + ".getConnection"); + return DriverManager.getConnection("jdbc:apache:commons:dbcp:topia"); + } finally { + CallAnalyse.exit(PersistenceStorageJDBCMultiTable.class.getName() + ".getConnection"); + } } @@ -339,42 +383,47 @@ * cree. */ protected void checkManagementTable() throws SQLException { - Connection conn = getConnection(); try{ + CallAnalyse.enter(PersistenceStorageJDBCMultiTable.class.getName() + ".checkManagementTable"); + Connection conn = getConnection(); try{ - PreparedStatement sta = null; - String sql = MessageFormat.format(SQL.getProperty(SQL_TABLE_EXISTS), "topia_mapping_table"); - sta = conn.prepareStatement(sql); - sta.execute(); - }catch(SQLException eee){ - log.info("Creating mapping table ..."); - conn.rollback(); - PreparedStatement sta = null; - String sql = SQL.getProperty(SQL_CREATE_TABLE_MAPPING); - sta = conn.prepareStatement(sql); - sta.execute(); - conn.commit(); - log.info("... mapping table created"); - } + try{ + PreparedStatement sta = null; + String sql = MessageFormat.format(SQL.getProperty(SQL_TABLE_EXISTS), "topia_mapping_table"); + sta = conn.prepareStatement(sql); + sta.execute(); + }catch(SQLException eee){ + log.info("Creating mapping table ..."); + conn.rollback(); + PreparedStatement sta = null; + String sql = SQL.getProperty(SQL_CREATE_TABLE_MAPPING); + sta = conn.prepareStatement(sql); + sta.execute(); + conn.commit(); + log.info("... mapping table created"); + } - try{ - PreparedStatement sta = null; - String sql = MessageFormat.format(SQL.getProperty(SQL_TABLE_EXISTS), "topia_heritage_table"); - sta = conn.prepareStatement(sql); - sta.execute(); - }catch(SQLException eee){ - log.info("Creating heritage table ..."); - conn.rollback(); - PreparedStatement sta = null; - String sql = SQL.getProperty(SQL_CREATE_TABLE_HERITAGE); - sta = conn.prepareStatement(sql); - sta.execute(); - conn.commit(); - log.info("... heritage table created"); - } + try{ + PreparedStatement sta = null; + String sql = MessageFormat.format(SQL.getProperty(SQL_TABLE_EXISTS), "topia_heritage_table"); + sta = conn.prepareStatement(sql); + sta.execute(); + }catch(SQLException eee){ + log.info("Creating heritage table ..."); + conn.rollback(); + PreparedStatement sta = null; + String sql = SQL.getProperty(SQL_CREATE_TABLE_HERITAGE); + sta = conn.prepareStatement(sql); + sta.execute(); + conn.commit(); + log.info("... heritage table created"); + } + } finally { + conn.close(); + } } finally { - conn.close(); + CallAnalyse.exit(PersistenceStorageJDBCMultiTable.class.getName() + ".checkManagementTable"); } } @@ -382,30 +431,34 @@ * Vide les vielles transactions non commitées */ protected void checkOldTransaction() throws SQLException { - Connection conn = getConnection(); try{ - PreparedStatement sta = null; - String sql = MessageFormat.format(SQL.getProperty(SQL_LOAD_ALL), "topia_mapping_table"); + CallAnalyse.enter(PersistenceStorageJDBCMultiTable.class.getName() + ".checkOldTransaction"); + Connection conn = getConnection(); + try{ + PreparedStatement sta = null; + String sql = MessageFormat.format(SQL.getProperty(SQL_LOAD_ALL), "topia_mapping_table"); - sta = conn.prepareStatement(sql); - ResultSet rs = sta.executeQuery(); - while (rs.next()){ - String classname = rs.getString("topia_class"); - String tablename = rs.getString("topia_table"); - long schemaVersion = rs.getLong("topia_schemaVersion"); - - log.info("purge table " + tablename + " ..."); - PreparedStatement purge = null; - sql = MessageFormat.format(SQL.getProperty(SQL_PURGE_TABLE), tablename); - purge = conn.prepareStatement(sql); - purge.execute(); - conn.commit(); - log.info("... table " + tablename + " purged"); + sta = conn.prepareStatement(sql); + ResultSet rs = sta.executeQuery(); + while (rs.next()){ + String classname = rs.getString("topia_class"); + String tablename = rs.getString("topia_table"); + long schemaVersion = rs.getLong("topia_schemaVersion"); + + log.info("purge table " + tablename + " ..."); + PreparedStatement purge = null; + sql = MessageFormat.format(SQL.getProperty(SQL_PURGE_TABLE), tablename); + purge = conn.prepareStatement(sql); + purge.execute(); + conn.commit(); + log.info("... table " + tablename + " purged"); + } + } finally { + conn.close(); } } finally { - conn.close(); + CallAnalyse.exit(PersistenceStorageJDBCMultiTable.class.getName() + ".checkOldTransaction"); } - } /** @@ -414,75 +467,85 @@ * la migration des objets vers la nouvelle version est faite automatiquement */ protected void checkSchemaVersion() throws SQLException, TopiaPersistenceException { - Connection conn = getConnection(); try{ - PreparedStatement sta = null; - String sql = MessageFormat.format(SQL.getProperty(SQL_LOAD_ALL), "topia_mapping_table"); - sta = conn.prepareStatement(sql); - ResultSet rs = sta.executeQuery(); - while (rs.next()){ - String classname = rs.getString("topia_class"); - String tablename = rs.getString("topia_table"); - long schemaVersion = rs.getLong("topia_schemaVersion"); - - long currentSchemaVersion = -1; - try{ - Class clazz = Class.forName(classname); - currentSchemaVersion = ClassInfoHelper.getSchemaVersion(clazz); - if (schemaVersion != currentSchemaVersion) { - log.info("Conversion du schema des objets " + classname - + " de la version " + schemaVersion + " vers " + currentSchemaVersion); - // pour tous les lignes de l'ancienne table - String allRowsSql = MessageFormat.format(SQL.getProperty(SQL_LOAD_ALL), tablename); - PreparedStatement allRows = conn.prepareStatement(allRowsSql); - ResultSet row = allRows.executeQuery(); - while(row.next()){ - // chargement d'un tpo - String id = row.getString("topia_id"); - TopiaPersistenceObject tpo = new TopiaPersistenceObject(id); - loadTpo(row, null, tpo, true); - // convert du tpo - tpo = convert(tpo, schemaVersion); - // storage du tpo dans la nouvelle table - store(conn, null, tpo); - } - // Suppression de l'ancienne table dans le mapping - rs.deleteRow(); + CallAnalyse.enter(PersistenceStorageJDBCMultiTable.class.getName() + ".checkSchemaVersion"); + Connection conn = getConnection(); + try{ + PreparedStatement sta = null; + String sql = MessageFormat.format(SQL.getProperty(SQL_LOAD_ALL), "topia_mapping_table"); + sta = conn.prepareStatement(sql); + ResultSet rs = sta.executeQuery(); + while (rs.next()){ + String classname = rs.getString("topia_class"); + String tablename = rs.getString("topia_table"); + long schemaVersion = rs.getLong("topia_schemaVersion"); - // Suppression de l'ancienne table - String deleteSql = MessageFormat.format(SQL.getProperty(SQL_DROP_TABLE), tablename); - PreparedStatement delete = conn.prepareStatement(deleteSql); - delete.execute(); - delete.close(); + long currentSchemaVersion = -1; + try{ + Class clazz = Class.forName(classname); + currentSchemaVersion = ClassInfoHelper.getSchemaVersion(clazz); + if (schemaVersion != currentSchemaVersion) { + log.info("Conversion du schema des objets " + classname + + " de la version " + schemaVersion + " vers " + currentSchemaVersion); + // pour tous les lignes de l'ancienne table + String allRowsSql = MessageFormat.format(SQL.getProperty(SQL_LOAD_ALL), tablename); + PreparedStatement allRows = conn.prepareStatement(allRowsSql); + ResultSet row = allRows.executeQuery(); + while(row.next()){ + // chargement d'un tpo + String id = row.getString("topia_id"); + TopiaPersistenceObject tpo = new TopiaPersistenceObject(id); + loadTpo(row, null, tpo, true); + // convert du tpo + tpo = convert(tpo, schemaVersion); + // storage du tpo dans la nouvelle table + store(conn, null, tpo); + } + // Suppression de l'ancienne table dans le mapping + rs.deleteRow(); + + // Suppression de l'ancienne table + String deleteSql = MessageFormat.format(SQL.getProperty(SQL_DROP_TABLE), tablename); + PreparedStatement delete = conn.prepareStatement(deleteSql); + delete.execute(); + delete.close(); - conn.commit(); + conn.commit(); + } + } catch(SQLException eee) { + throw new TopiaPersistenceException( + "Impossible de convertir les objets: " + + classname + "(" + schemaVersion + "->" + + currentSchemaVersion +")", eee); + } catch(ClassNotFoundException eee){ + throw new TopiaPersistenceException( + "Impossible de retrouver la classe demandée: " + + classname, eee); } - } catch(SQLException eee) { - throw new TopiaPersistenceException( - "Impossible de convertir les objets: " - + classname + "(" + schemaVersion + "->" - + currentSchemaVersion +")", eee); - } catch(ClassNotFoundException eee){ - throw new TopiaPersistenceException( - "Impossible de retrouver la classe demandée: " - + classname, eee); } + } finally { + conn.close(); } } finally { - conn.close(); + CallAnalyse.exit(PersistenceStorageJDBCMultiTable.class.getName() + ".checkSchemaVersion"); } } protected String getSQLFieldDeclaration(Class clazz) { - StringBuffer result = new StringBuffer(); - String [] fieldnames = ClassInfoHelper.fields(clazz); - Class [] fieldTypes = ClassInfoHelper.fieldTypes(clazz); - for(int i=0; i 60){ - result = result.substring(result.length() - 60); - } + if(result.length() > 60){ + result = result.substring(result.length() - 60); + } - return result; + return result; + } finally { + CallAnalyse.exit(PersistenceStorageJDBCMultiTable.class.getName() + ".generateTableName"); + } } /** @@ -517,73 +585,81 @@ * le nom de la table depend de la version du schema */ // FIXME faire un cache protected String getTableName(Class clazz) throws SQLException { - String result = null; - String classname = clazz.getName(); - long schemaVersion = ClassInfoHelper.getSchemaVersion(clazz); - - Connection conn = getConnection(); - try{ - PreparedStatement sta = null; - String sql = SQL.getProperty(SQL_GET_TABLE_NAME); - sta = conn.prepareStatement(sql); - sta.setString(1, classname); - sta.setLong(2, schemaVersion); - - ResultSet rs = sta.executeQuery(); - if(rs.next()){ - result = rs.getString("topia_table"); - } - sta.close(); - + try{ + CallAnalyse.enter(PersistenceStorageJDBCMultiTable.class.getName() + ".getTableName"); + String result = tableNameCache.get(clazz); if(result == null){ - result = generateTableName(clazz); - log.info("Ajout de la table " + result + " pour " + classname + "("+schemaVersion+")"); - sql = SQL.getProperty(SQL_INSERT_MAPPING); - sta = conn.prepareStatement(sql); - sta.setString(1, classname); - sta.setString(2, result); - sta.setLong(3, schemaVersion); - sta.execute(); - sta.close(); + String classname = clazz.getName(); + long schemaVersion = ClassInfoHelper.getSchemaVersion(clazz); - log.info("creation de la nouvelle table: " + result); - String fieldsDeclaration = getSQLFieldDeclaration(clazz); - String newTableSql = MessageFormat.format(SQL.getProperty(SQL_CREATE_TABLE_DATA), result, fieldsDeclaration); - log.info("Create data sql: " + newTableSql); - System.out.println("Create data sql: " + newTableSql); - PreparedStatement newTable = conn.prepareStatement(newTableSql); - newTable.execute(); - newTable.close(); - - log.info("Mise a jour de la table d'heritage"); - // on vide le cache - childCache.clear(); - // on vide la table d'heritage pour cette classe - sql = SQL.getProperty(SQL_REMOVE_HERITAGE); - sta = conn.prepareStatement(sql); - sta.setString(1, classname); - sta.execute(); - sta.close(); + Connection conn = getConnection(); + try{ + PreparedStatement sta = null; + String sql = SQL.getProperty(SQL_GET_TABLE_NAME); + sta = conn.prepareStatement(sql); + sta.setString(1, classname); + sta.setLong(2, schemaVersion); + + ResultSet rs = sta.executeQuery(); + if(rs.next()){ + result = rs.getString("topia_table"); + } + sta.close(); - // on remet la table d'heritage a jour pour cette classe - Class[] classes = clazz.getInterfaces(); - for(Class c:classes){ - if(TopiaEntity.class.isAssignableFrom(c) - && !TopiaEntity.class.equals(c)){ - sql = SQL.getProperty(SQL_INSERT_HERITAGE); + if(result == null){ + result = generateTableName(clazz); + log.info("Ajout de la table " + result + " pour " + classname + "("+schemaVersion+")"); + sql = SQL.getProperty(SQL_INSERT_MAPPING); sta = conn.prepareStatement(sql); - sta.setString(1, c.getName()); - sta.setString(2, classname); + sta.setString(1, classname); + sta.setString(2, result); + sta.setLong(3, schemaVersion); sta.execute(); sta.close(); + + log.info("creation de la nouvelle table: " + result); + String fieldsDeclaration = getSQLFieldDeclaration(clazz); + String newTableSql = MessageFormat.format(SQL.getProperty(SQL_CREATE_TABLE_DATA), result, fieldsDeclaration); + log.info("Create data sql: " + newTableSql); + System.out.println("Create data sql: " + newTableSql); + PreparedStatement newTable = conn.prepareStatement(newTableSql); + newTable.execute(); + newTable.close(); + + log.info("Mise a jour de la table d'heritage"); + // on vide le cache + childCache.clear(); + // on vide la table d'heritage pour cette classe + sql = SQL.getProperty(SQL_REMOVE_HERITAGE); + sta = conn.prepareStatement(sql); + sta.setString(1, classname); + sta.execute(); + sta.close(); + + // on remet la table d'heritage a jour pour cette classe + Class[] classes = clazz.getInterfaces(); + for(Class c:classes){ + if(TopiaEntity.class.isAssignableFrom(c) + && !TopiaEntity.class.equals(c)){ + sql = SQL.getProperty(SQL_INSERT_HERITAGE); + sta = conn.prepareStatement(sql); + sta.setString(1, c.getName()); + sta.setString(2, classname); + sta.execute(); + sta.close(); + } + } + conn.commit(); } + } finally { + conn.close(); } - conn.commit(); + tableNameCache.put(clazz, result); } + return result; } finally { - conn.close(); + CallAnalyse.exit(PersistenceStorageJDBCMultiTable.class.getName() + ".getTableName"); } - return result; } /** @@ -593,100 +669,107 @@ * Pour cela des qu'un objet est ajouter, on verifie qu'on a deja marqué * ces parents comme etant c parent. */ - protected String [] getChidTableName(Class clazz) throws SQLException { - String [] result = childCache.get(clazz); - if(result == null){ - Connection conn = getConnection(); - try { - ArrayList tmp = getChidTableName(conn, clazz.getName()); - result = tmp.toArray(new String[tmp.size()]); - childCache.put(clazz, result); - } finally { - conn.close(); + public String [] getChidTableName(Class clazz) throws SQLException { + try{ + CallAnalyse.enter(PersistenceStorageJDBCMultiTable.class.getName() + ".getChidTableName(Class)"); + String [] result = childCache.get(clazz); + if(result == null){ + Connection conn = getConnection(); + try { + ArrayList tmp = getChidTableName(conn, clazz.getName()); + result = tmp.toArray(new String[tmp.size()]); + childCache.put(clazz, result); + } finally { + conn.close(); + } } + return result; + } finally { + CallAnalyse.exit(PersistenceStorageJDBCMultiTable.class.getName() + ".getChidTableName(Class)"); } - return result; } protected ArrayList getChidTableName(Connection conn, String classname) throws SQLException { - String sql = SQL.getProperty(SQL_GET_CHILD); - PreparedStatement sta = conn.prepareStatement(sql); - sta.setString(1, classname); - ResultSet rs = sta.executeQuery(); - ArrayList result = new ArrayList(); - ArrayList tmp = new ArrayList(); - while(rs.next()){ - tmp.add(rs.getString("topia_child")); - } - sta.close(); - result.addAll(tmp); - for(String child: tmp){ - result.addAll(getChidTableName(conn, child)); - } - return result; - } - - public long time_store = 0; - public long time_managementExists = 0; - public long time_storeOne = 0; - public long time_storeList = 0; - public long time_saveManagement = 0; - public long time_saveData = 0; - public long time_objectToDatabase = 0; - public long time_databaseToObject = 0; + try{ + CallAnalyse.enter(PersistenceStorageJDBCMultiTable.class.getName() + ".getChidTableName(Connection, String)"); + String sql = SQL.getProperty(SQL_GET_CHILD); + PreparedStatement sta = conn.prepareStatement(sql); + sta.setString(1, classname); + ResultSet rs = sta.executeQuery(); + ArrayList result = new ArrayList(); + ArrayList tmp = new ArrayList(); + while(rs.next()){ + tmp.add(rs.getString("topia_child")); + } + sta.close(); + result.addAll(tmp); + for(String child: tmp){ + result.addAll(getChidTableName(conn, child)); + } + return result; + } finally { + CallAnalyse.exit(PersistenceStorageJDBCMultiTable.class.getName() + ".getChidTableName(Connection, String)"); + } + } public void store(TopiaContext context, Collection tpos) throws TopiaPersistenceException { - long time = System.currentTimeMillis(); - Connection conn = null; try{ - conn = getConnection(); + CallAnalyse.enter(PersistenceStorageJDBCMultiTable.class.getName() + ".store(TopiaContext, Collection)"); + Connection conn = null; try{ - for(TopiaPersistenceObject tpo: tpos){ - store(conn, context, tpo); - } - } finally { - conn.commit(); - conn.close(); - } - } catch(SQLException eee) { - if(conn != null){ + conn = getConnection(); try{ - conn.rollback(); + for(TopiaPersistenceObject tpo: tpos){ + store(conn, context, tpo); + } + } finally { + conn.commit(); conn.close(); } - catch(SQLException zzz){ - log.info("Erreur durant le rollback du a une exception", zzz); + } catch(SQLException eee) { + if(conn != null){ + try{ + conn.rollback(); + conn.close(); + } + catch(SQLException zzz){ + log.info("Erreur durant le rollback du a une exception", zzz); + } } + throw new TopiaPersistenceException("Erreur durant la sauvegarde de la liste d'entites", eee); } - throw new TopiaPersistenceException("Erreur durant la sauvegarde de la liste d'entites", eee); + } finally { + CallAnalyse.exit(PersistenceStorageJDBCMultiTable.class.getName() + ".store(TopiaContext, Collection)"); } - time_storeList += System.currentTimeMillis() - time; } public void store(TopiaContext context, TopiaPersistenceObject tpo) throws TopiaPersistenceException { - long time = System.currentTimeMillis(); - Connection conn = null; try{ - conn = getConnection(); + CallAnalyse.enter(PersistenceStorageJDBCMultiTable.class.getName() + ".store(TopiaContext, TopiaPersistenceObject)"); + Connection conn = null; try{ - store(conn, context, tpo); - } finally { - conn.commit(); - conn.close(); - } - } catch(SQLException eee) { - if(conn != null){ + conn = getConnection(); try{ - conn.rollback(); + store(conn, context, tpo); + } finally { + conn.commit(); conn.close(); } - catch(SQLException zzz){ - log.info("erreur précédente", eee); - log.info("Erreur durant le rollback du a une exception", zzz); + } catch(SQLException eee) { + if(conn != null){ + try{ + conn.rollback(); + conn.close(); + } + catch(SQLException zzz){ + log.info("erreur précédente", eee); + log.info("Erreur durant le rollback du a une exception", zzz); + } } + throw new TopiaPersistenceException("Erreur durant la sauvegarde de l'entite: " + tpo.getManagement().getId(), eee); } - throw new TopiaPersistenceException("Erreur durant la sauvegarde de l'entite: " + tpo.getManagement().getId(), eee); + } finally { + CallAnalyse.exit(PersistenceStorageJDBCMultiTable.class.getName() + ".store(TopiaContext, TopiaPersistenceObject)"); } - time_storeOne += System.currentTimeMillis() - time; } /** @@ -697,93 +780,145 @@ */ protected void store(Connection conn, TopiaContext context, TopiaPersistenceObject tpo) throws SQLException, TopiaPersistenceException { - long time = System.currentTimeMillis(); - // si l'objet n'etait pas encore dans la transaction, on le met - if(context != null){ - tpo.getManagement().setDate(context.getTransaction().getId()); - } - - boolean exists = exists(conn, context, tpo); - if(exists){ - // l'objet existait on le met a jour - saveData(conn, context, tpo, false); - } else { - // l'objet n'existait pas, on le creer - saveData(conn, context, tpo, true); - } - time_store += System.currentTimeMillis() - time; - } - - protected boolean exists(Connection conn, TopiaContext context, - TopiaPersistenceObject tpo) throws SQLException, TopiaPersistenceException { - long time = System.currentTimeMillis(); - boolean result = false; - - Class clazz = tpo.getManagement().getEntityClass(); - String tablename = getTableName(clazz); - String sql = MessageFormat.format(SQL.getProperty(SQL_LOAD_DATA), tablename); - PreparedStatement sta = conn.prepareStatement(sql); - try{ - sta.setString(1, tpo.getManagement().getId()); - sta.setLong(2, tpo.getManagement().getDate()); - ResultSet rr = sta.executeQuery(); - result = rr.next(); + try{ + CallAnalyse.enter(PersistenceStorageJDBCMultiTable.class.getName() + ".store"); + // si l'objet n'etait pas encore dans la transaction, on le met + if(context != null){ + tpo.getManagement().setDate(context.getTransaction().getId()); + } + + // boolean exists = exists(conn, context, tpo); + // if(exists){ + // l'objet existait on le met a jour + // saveData(conn, context, tpo, false); + // } else { + // l'objet n'existait pas, on le creer + // saveData(conn, context, tpo, true); + // } + + long topia_longdate = getLastLongdate(conn, context, tpo); + if(topia_longdate == 0){ + // l'objet n'existait pas, on le cree + saveData(conn, context, tpo, true); + } else { + if(topia_longdate != context.getTransaction().getId()){ + // l'objet n'existait pas pour cette transaction, on le cree + copyForTransaction(conn, context, tpo, topia_longdate); + } + // l'objet existe on le met a jour + saveData(conn, context, tpo, false); + } + } finally { - sta.close(); + CallAnalyse.exit(PersistenceStorageJDBCMultiTable.class.getName() + ".store"); } - time_managementExists += System.currentTimeMillis() - time; - return result; } /** - * Demande la restauration de l'entité dans le context de la transaction + * Copy une donnée pour la mettre dans la transaction + * @param conn la connection a la base a utiliser + * @param context le context dans lequel la demande est faite + * @param tpo le tpo a copier + * @param topia_longdate la date de l'objet source */ - public void restore(TopiaContext context, TopiaPersistenceObject tpo) throws TopiaPersistenceException { - if(!(tpo.getManagement().isUnloaded() || tpo.getAskedFields().size() != 0 || tpo.getManagement().isRollbacked())){ - // deja chargé et pas de champs a charger on sort tout de suite - return; - } + protected void copyForTransaction(Connection conn, TopiaContext context, + TopiaPersistenceObject tpo, long topia_longdate) throws SQLException { try{ + CallAnalyse.enter(PersistenceStorageJDBCMultiTable.class.getName() + ".copyForTransaction"); Class clazz = tpo.getManagement().getEntityClass(); String tablename = getTableName(clazz); - Connection conn = getConnection(); + String fieldnames = ""; + for(String fieldname: ClassInfoHelper.fields(clazz)){ + fieldnames += ", " + objectToDatabaseFieldName(fieldname); + } + String sql = MessageFormat.format(SQL.getProperty(SQL_COPY_DATA), tablename, fieldnames, ""+context.getTransaction().getId()); + PreparedStatement sta = conn.prepareStatement(sql); + try{ + sta.setString(1, tpo.getId()); + sta.setLong(2, topia_longdate); + sta.execute(); + } finally { + sta.close(); + } + } finally { + CallAnalyse.exit(PersistenceStorageJDBCMultiTable.class.getName() + ".copyForTransaction"); + } + } + + // protected boolean exists(Connection conn, TopiaContext context, + // TopiaPersistenceObject tpo) throws SQLException, TopiaPersistenceException { + // long time = System.currentTimeMillis(); + // boolean result = false; + + // Class clazz = tpo.getManagement().getEntityClass(); + // String tablename = getTableName(clazz); + // String sql = MessageFormat.format(SQL.getProperty(SQL_LOAD_DATA), tablename); + // PreparedStatement sta = conn.prepareStatement(sql); + // try{ + // sta.setString(1, tpo.getManagement().getId()); + // sta.setLong(2, tpo.getManagement().getDate()); + // ResultSet rr = sta.executeQuery(); + // result = rr.next(); + // } finally { + // sta.close(); + // } + // return result; + // } + + /** + * Demande la restauration de l'entité dans le context de la transaction + */ + public void restore(TopiaContext context, TopiaPersistenceObject tpo) throws TopiaPersistenceException { + try{ + CallAnalyse.enter(PersistenceStorageJDBCMultiTable.class.getName() + ".restore"); + if(!(tpo.getManagement().isUnloaded() || tpo.getAskedFields().size() != 0 || tpo.getManagement().isRollbacked())){ + // deja chargé et pas de champs a charger on sort tout de suite + return; + } try{ - String sql = MessageFormat.format(SQL.getProperty(SQL_LOAD_DATA), tablename); - PreparedStatement sta = conn.prepareStatement(sql); + Class clazz = tpo.getManagement().getEntityClass(); + String tablename = getTableName(clazz); + Connection conn = getConnection(); try{ - sta.setString(1, tpo.getManagement().getId()); - sta.setLong(2, context.getTransaction().getId()); - ResultSet management = sta.executeQuery(); - if(!management.next()){ - // on a pas trouve un management specifique pour la - // transaction on recherche le plus recent des objet - // commit pour cette transaction - sta.close(); - String query = MessageFormat.format(SQL.getProperty(SQL_LOAD_HISTORY), tablename); - query = Util.setAllMultipleIds(query, context.getTransaction()); - sta = conn.prepareStatement(query); - sta.setMaxRows(1); // on veut uniquement le premier + String sql = MessageFormat.format(SQL.getProperty(SQL_LOAD_DATA), tablename); + PreparedStatement sta = conn.prepareStatement(sql); + try{ sta.setString(1, tpo.getManagement().getId()); - sta.setLong(2, -context.getTransaction().getId()); - management = sta.executeQuery(); + sta.setLong(2, context.getTransaction().getId()); + ResultSet management = sta.executeQuery(); if(!management.next()){ - // on a pas trouvé d'objet sattisfaisant la demande - throw new TopiaPersistenceException("This object(" - + tpo.getManagement().getId() + ") don't exist in this transaction(" - + context.getTransaction().getId() + ")"); + // on a pas trouve un management specifique pour la + // transaction on recherche le plus recent des objet + // commit pour cette transaction + sta.close(); + String query = MessageFormat.format(SQL.getProperty(SQL_LOAD_HISTORY), tablename); + query = Util.setAllMultipleIds(query, context.getTransaction()); + sta = conn.prepareStatement(query); + sta.setMaxRows(1); // on veut uniquement le premier + sta.setString(1, tpo.getManagement().getId()); + sta.setLong(2, -context.getTransaction().getId()); + management = sta.executeQuery(); + if(!management.next()){ + // on a pas trouvé d'objet sattisfaisant la demande + throw new TopiaPersistenceException("This object(" + + tpo.getManagement().getId() + ") don't exist in this transaction(" + + context.getTransaction().getId() + ")"); + } } - } - loadTpo(management, context, tpo, false); + loadTpo(management, context, tpo, false); + } finally { + sta.close(); + } + conn.commit(); } finally { - sta.close(); + conn.close(); } - conn.commit(); - } finally { - conn.close(); + } catch(SQLException eee) { + throw new TopiaPersistenceException("Erreur durant la restauration de l'objet: " + tpo.getManagement().getId(), eee); } - } catch(SQLException eee) { - throw new TopiaPersistenceException("Erreur durant la restauration de l'objet: " + tpo.getManagement().getId(), eee); + } finally { + CallAnalyse.exit(PersistenceStorageJDBCMultiTable.class.getName() + ".restore"); } } @@ -805,18 +940,23 @@ } protected JDBCTransformer getTransformer(Class type) { - // Les entities sont transformer en String, dans le proxy - // Il faut donc gerer les entities comme des Strings - if(TopiaEntity.class.isAssignableFrom(type)){ - type = String.class; - } + try{ + CallAnalyse.enter(PersistenceStorageJDBCMultiTable.class.getName() + ".getTransformer"); + // Les entities sont transformer en String, dans le proxy + // Il faut donc gerer les entities comme des Strings + if(TopiaEntity.class.isAssignableFrom(type)){ + type = String.class; + } - JDBCTransformer result = JDBCTransformerFactory.getTransformer(type); - if(result == null){ - log.debug("Can't get transformer for " + type.getName() + " get Object transformer"); - result = JDBCTransformerFactory.getTransformer(Object.class); + JDBCTransformer result = JDBCTransformerFactory.getTransformer(type); + if(result == null){ + log.debug("Can't get transformer for " + type.getName() + " get Object transformer"); + result = JDBCTransformerFactory.getTransformer(Object.class); + } + return result; + } finally { + CallAnalyse.exit(PersistenceStorageJDBCMultiTable.class.getName() + ".getTransformer"); } - return result; } /** @@ -826,18 +966,23 @@ * @param value l'objet sur lequel il faut appeler setContext */ protected void setContext(TopiaContext context, Object value) throws TopiaPersistenceException { - if(context != null && value != null){ - // s'il a une methode setContext(TopiaContext) - // alors on l'appelle avec le context qui est en parametre - Method m = MethodUtils.getMatchingAccessibleMethod( - value.getClass(), "setContext", new Class[]{context.getClass()}); - if(m != null){ - try{ - m.invoke(value, context); - }catch(Exception eee){ - log.warn("Can't set context on object", eee); + try{ + CallAnalyse.enter(PersistenceStorageJDBCMultiTable.class.getName() + ".setContext"); + if(context != null && value != null){ + // s'il a une methode setContext(TopiaContext) + // alors on l'appelle avec le context qui est en parametre + Method m = MethodUtils.getMatchingAccessibleMethod( + value.getClass(), "setContext", new Class[]{context.getClass()}); + if(m != null){ + try{ + m.invoke(value, context); + }catch(Exception eee){ + log.warn("Can't set context on object", eee); + } } } + } finally { + CallAnalyse.exit(PersistenceStorageJDBCMultiTable.class.getName() + ".setContext"); } } @@ -855,43 +1000,39 @@ public void loadTpo(ResultSet rs, TopiaContext context, TopiaPersistenceObject tpo, boolean forceLoadAllField) throws SQLException, TopiaPersistenceException { - Class clazz = tpo.getManagement().getEntityClass(); + try{ + CallAnalyse.enter(PersistenceStorageJDBCMultiTable.class.getName() + ".loadTpo"); + Class clazz = tpo.getManagement().getEntityClass(); - if(tpo.getManagement().isUnloaded() || tpo.getManagement().isRollbacked()){ - tpo.getManagement().setDate(rs.getLong("topia_longdate")); - tpo.getManagement().setStored(true); - tpo.getManagement().setDeleted(rs.getBoolean("topia_isDeleted")); - // l'objet quoi qu'il arrive ne sera plus nouveau - } - - Collection fieldnames = null; - // FIXME pour l'instant on force le chargement de tous les champs - // tout le temps, car sinon on a un probleme lors de la sauvegarde - // de l'objet dans une transaction, car il faut reecrire tous les - // champs, mais on ne les a pas s'il ne sont pas chargé. - // Il faudrait lors de la sauvegarde faire une copie en SQL de la - // derniere ligne valide pour l'objet en modifiant simplement l'id - // de transaction. Puis faire un update des données. - // La copie en SQL est plus rapide, car si on charge le TPO, il - // y a potentiellement des conversions de type - if(forceLoadAllField || true) { - fieldnames = Arrays.asList(ClassInfoHelper.fields(clazz)); - } else { - fieldnames = tpo.getAskedFields(); - } - for(String fieldname: fieldnames){ - // si pas UNLOADED, ca veut dire que l'utilisateur a modifier - // la valeur, et qu'il ne faut pas perdre cette valeur - if(tpo.getData().getField(fieldname) == tpo.getData().UNLOADED){ - Class fieldType = ClassInfoHelper.fieldType(clazz, fieldname); - JDBCTransformer t = getTransformer(fieldType); - Object value = t.getValue(rs, - objectToDatabaseFieldName(fieldname)); - setContext(context, value); - tpo.getData().setField(fieldname, value); + if(tpo.getManagement().isUnloaded() || tpo.getManagement().isRollbacked()){ + tpo.getManagement().setDate(rs.getLong("topia_longdate")); + tpo.getManagement().setStored(true); + tpo.getManagement().setDeleted(rs.getBoolean("topia_isDeleted")); + // l'objet quoi qu'il arrive ne sera plus nouveau } + + Collection fieldnames = null; + if(forceLoadAllField) { + fieldnames = Arrays.asList(ClassInfoHelper.fields(clazz)); + } else { + fieldnames = tpo.getAskedFields(); + } + for(String fieldname: fieldnames){ + // si pas UNLOADED, ca veut dire que l'utilisateur a modifier + // la valeur, et qu'il ne faut pas perdre cette valeur + if(tpo.getData().getField(fieldname) == tpo.getData().UNLOADED){ + Class fieldType = ClassInfoHelper.fieldType(clazz, fieldname); + JDBCTransformer t = getTransformer(fieldType); + Object value = t.getValue(rs, + objectToDatabaseFieldName(fieldname)); + setContext(context, value); + tpo.getData().setField(fieldname, value); + } + } + tpo.getAskedFields().clear(); + } finally { + CallAnalyse.exit(PersistenceStorageJDBCMultiTable.class.getName() + ".loadTpo"); } - tpo.getAskedFields().clear(); } /** @@ -901,66 +1042,107 @@ protected void saveData(Connection conn, TopiaContext context, TopiaPersistenceObject tpo, boolean forceInsert) throws SQLException, TopiaPersistenceException { - // TODO supprimer le time apres analyse des perfs - long time = System.currentTimeMillis(); - synchronized(tpo){ - Class clazz = tpo.getManagement().getEntityClass(); - String tablename = getTableName(clazz); + try{ + CallAnalyse.enter(PersistenceStorageJDBCMultiTable.class.getName() + ".saveData"); + synchronized(tpo){ + Class clazz = tpo.getManagement().getEntityClass(); + String tablename = getTableName(clazz); - Collection fieldnames = null; - if(forceInsert) { - fieldnames = Arrays.asList(ClassInfoHelper.fields(clazz)); - } else { - fieldnames = tpo.getModifiedFields(); - } - - String sql = null; - if(forceInsert){ - // rechercher les champs a inserer depuis le tpo pour construire - // la bonne requete - String fields = ""; - String qmarks = ""; - for(String fieldname: fieldnames){ - fields += ", " + objectToDatabaseFieldName(fieldname); - qmarks += ", ?"; - } - sql = MessageFormat.format(SQL.getProperty(SQL_INSERT_DATA), tablename, fields, qmarks); + Collection fieldnames = null; + if(forceInsert) { + fieldnames = Arrays.asList(ClassInfoHelper.fields(clazz)); } else { - // rechercher les champs a updater depuis le tpo pour construire - // la bonne requete - String fields = ""; - for(String fieldname: fieldnames){ - fields += ", " + objectToDatabaseFieldName(fieldname) + "=?"; - } - sql = MessageFormat.format(SQL.getProperty(SQL_UPDATE_DATA), tablename, fields); + fieldnames = tpo.getModifiedFields(); } - PreparedStatement insert = conn.prepareStatement(sql); - try{ - int i = 1; - insert.setString(i++, tpo.getManagement().getId()); - insert.setLong(i++, tpo.getManagement().getDate()); - insert.setString(i++, clazz.getName()); - insert.setBoolean(i++, tpo.getManagement().isNew()); - insert.setBoolean(i++, tpo.getManagement().isDeleted()); - for(String fieldname: fieldnames){ - Object value = tpo.getData().get(fieldname); - Class fieldType = ClassInfoHelper.fieldType(clazz, fieldname); - JDBCTransformer t = getTransformer(fieldType); - t.setValue(insert, i++, value); - } - if(!forceInsert){ + String sql = null; + if(forceInsert){ + // rechercher les champs a inserer depuis le tpo pour construire + // la bonne requete + String fields = ""; + String qmarks = ""; + for(String fieldname: fieldnames){ + fields += ", " + objectToDatabaseFieldName(fieldname); + qmarks += ", ?"; + } + sql = MessageFormat.format(SQL.getProperty(SQL_INSERT_DATA), tablename, fields, qmarks); + } else { + // rechercher les champs a updater depuis le tpo pour construire + // la bonne requete + String fields = ""; + for(String fieldname: fieldnames){ + fields += ", " + objectToDatabaseFieldName(fieldname) + "=?"; + } + sql = MessageFormat.format(SQL.getProperty(SQL_UPDATE_DATA), tablename, fields); + } + PreparedStatement insert = conn.prepareStatement(sql); + try{ + int i = 1; insert.setString(i++, tpo.getManagement().getId()); insert.setLong(i++, tpo.getManagement().getDate()); + insert.setString(i++, clazz.getName()); + insert.setBoolean(i++, tpo.getManagement().isNew()); + insert.setBoolean(i++, tpo.getManagement().isDeleted()); + for(String fieldname: fieldnames){ + Object value = tpo.getData().get(fieldname); + Class fieldType = ClassInfoHelper.fieldType(clazz, fieldname); + JDBCTransformer t = getTransformer(fieldType); + t.setValue(insert, i++, value); + } + + if(!forceInsert){ + insert.setString(i++, tpo.getManagement().getId()); + insert.setLong(i++, tpo.getManagement().getDate()); + } + + insert.execute(); + } finally { + insert.close(); } + tpo.getModifiedFields().clear(); + } + } finally { + CallAnalyse.exit(PersistenceStorageJDBCMultiTable.class.getName() + ".saveData"); + } + } - insert.execute(); + /** + * Retourn la derniere version d'un objet, il ne faut pas qu'il soit + * marqué deleted pour que la méthode retourne une valeur. + * @param context le context de la demande + * @param tpo le tpo visé + * @return le topia_longdate date, on 0 si l'objet n'existe pas encore + */ + public long getLastLongdate(Connection conn, TopiaContext context, TopiaPersistenceObject tpo) throws SQLException { + try{ + CallAnalyse.enter(PersistenceStorageJDBCMultiTable.class.getName() + ".getLastLongdate"); + long result = 0; + String tablename = getTableName(tpo.getManagement().getEntityClass()); + String query = MessageFormat.format(SQL.getProperty(SQL_LOAD_HISTORY), tablename); + query = Util.setAllMultipleIds(query, context.getTransaction()); + PreparedStatement sta = conn.prepareStatement(query); + try{ + sta.setString(1, tpo.getId()); + // sta.setString(2, tpo.getId()); + // sta.setString(3, tpo.getId()); + sta.setLong(2, -context.getTransaction().getId()); + ResultSet rr = sta.executeQuery(); + while(rr.next()) { + long tmp = rr.getLong("topia_longdate"); + if(tmp == context.getTransaction().getId() || tmp > 0){ + if(!rr.getBoolean("topia_isDeleted")) { + result = tmp; + } + break; + } + } } finally { - insert.close(); + sta.close(); } - tpo.getModifiedFields().clear(); + return result; + } finally { + CallAnalyse.exit(PersistenceStorageJDBCMultiTable.class.getName() + ".getLastLongdate"); } - time_saveData += System.currentTimeMillis() - time; } /** @@ -968,39 +1150,44 @@ * context de la transaction */ public Collection getAllId(TopiaContext context) throws TopiaPersistenceException { - List result = new ArrayList(); try{ - Connection conn = getConnection(); + CallAnalyse.enter(PersistenceStorageJDBCMultiTable.class.getName() + ".getAllId"); + List result = new ArrayList(); try{ - String sql = MessageFormat.format(SQL.getProperty(SQL_LOAD_ALL), "topia_mapping_table"); - PreparedStatement allTable = conn.prepareStatement(sql); - ResultSet rs = allTable.executeQuery(); - while (rs.next()){ - String classname = rs.getString("topia_class"); - String tablename = rs.getString("topia_table"); + Connection conn = getConnection(); + try{ + String sql = MessageFormat.format(SQL.getProperty(SQL_LOAD_ALL), "topia_mapping_table"); + PreparedStatement allTable = conn.prepareStatement(sql); + ResultSet rs = allTable.executeQuery(); + while (rs.next()){ + String classname = rs.getString("topia_class"); + String tablename = rs.getString("topia_table"); - String query = MessageFormat.format(SQL.getProperty(SQL_GET_ALL_ID), tablename); - query = Util.setAllMultipleIds(query, context.getTransaction()); - PreparedStatement sta = conn.prepareStatement(query); - try{ - sta.setLong(1, -context.getTransaction().getId()); - sta.setLong(2, -context.getTransaction().getId()); - ResultSet rr = sta.executeQuery(); - while(rr.next()){ - result.add(rr.getString("topia_id")); + String query = MessageFormat.format(SQL.getProperty(SQL_GET_ALL_ID), tablename); + query = Util.setAllMultipleIds(query, context.getTransaction()); + PreparedStatement sta = conn.prepareStatement(query); + try{ + sta.setLong(1, -context.getTransaction().getId()); + sta.setLong(2, -context.getTransaction().getId()); + ResultSet rr = sta.executeQuery(); + while(rr.next()){ + result.add(rr.getString("topia_id")); + } + } finally { + sta.close(); } - } finally { - sta.close(); } + conn.commit(); + } finally { + conn.close(); } - conn.commit(); - } finally { - conn.close(); + } catch(SQLException eee) { + throw new TopiaPersistenceException("Erreur durant la recherche des objets existant", eee); } - } catch(SQLException eee) { - throw new TopiaPersistenceException("Erreur durant la recherche des objets existant", eee); + return result; + } finally { + CallAnalyse.exit(PersistenceStorageJDBCMultiTable.class.getName() + ".getAllId"); } - return result; } /** @@ -1026,39 +1213,44 @@ */ public void commitTransaction(TopiaContext context) throws TopiaPersistenceException { try{ - TopiaTransaction actualtt = context.getTransaction(); - TopiaTransaction newtt = context.getTransaction().regenerateTransaction(); - // peut-etre faire quelque chose comme dans beginTransaction ? - // Comme on a fait un regenerateTransaction, le parent a deja pris en compte le changement de transaction, alors il faut impérativement le valider (au cas où une erreur survienne) - context.setTransaction(newtt); - Connection conn = getConnection(); + CallAnalyse.enter(PersistenceStorageJDBCMultiTable.class.getName() + ".commitTransaction"); try{ - String allTableSql = MessageFormat.format(SQL.getProperty(SQL_LOAD_ALL), "topia_mapping_table"); - PreparedStatement allTable = conn.prepareStatement(allTableSql); - ResultSet rs = allTable.executeQuery(); - while (rs.next()){ - String classname = rs.getString("topia_class"); - String tablename = rs.getString("topia_table"); - - String sql = MessageFormat.format(SQL.getProperty(SQL_COMMIT_DATA), tablename); - PreparedStatement sta = conn.prepareStatement(sql); - try{ - sta.setLong(1, newtt.getCommitId()); - sta.setLong(2, actualtt.getId()); - sta.execute(); - } finally { - sta.close(); + TopiaTransaction actualtt = context.getTransaction(); + TopiaTransaction newtt = context.getTransaction().regenerateTransaction(); + // peut-etre faire quelque chose comme dans beginTransaction ? + // Comme on a fait un regenerateTransaction, le parent a deja pris en compte le changement de transaction, alors il faut impérativement le valider (au cas où une erreur survienne) + context.setTransaction(newtt); + Connection conn = getConnection(); + try{ + String allTableSql = MessageFormat.format(SQL.getProperty(SQL_LOAD_ALL), "topia_mapping_table"); + PreparedStatement allTable = conn.prepareStatement(allTableSql); + ResultSet rs = allTable.executeQuery(); + while (rs.next()){ + String classname = rs.getString("topia_class"); + String tablename = rs.getString("topia_table"); + + String sql = MessageFormat.format(SQL.getProperty(SQL_COMMIT_DATA), tablename); + PreparedStatement sta = conn.prepareStatement(sql); + try{ + sta.setLong(1, newtt.getCommitId()); + sta.setLong(2, actualtt.getId()); + sta.execute(); + } finally { + sta.close(); + } + } + conn.commit(); + } finally { + if(!conn.isClosed()){ + conn.close(); } } - conn.commit(); - } finally { - if(!conn.isClosed()){ - conn.close(); - } - } - } catch(SQLException eee){ - throw new TopiaPersistenceException("Erreur durant le commit transaction: " + context.getTransaction().getId(), eee); + } catch(SQLException eee){ + throw new TopiaPersistenceException("Erreur durant le commit transaction: " + context.getTransaction().getId(), eee); + } + } finally { + CallAnalyse.exit(PersistenceStorageJDBCMultiTable.class.getName() + ".commitTransaction"); } } @@ -1068,33 +1260,38 @@ */ public void rollbackTransaction(TopiaContext context) throws TopiaPersistenceException { try{ - Connection conn = getConnection(); + CallAnalyse.enter(PersistenceStorageJDBCMultiTable.class.getName() + ".rollbackTransaction"); try{ - String allTableSql = MessageFormat.format(SQL.getProperty(SQL_LOAD_ALL), "topia_mapping_table"); - PreparedStatement allTable = conn.prepareStatement(allTableSql); - ResultSet rs = allTable.executeQuery(); - while (rs.next()){ - String classname = rs.getString("topia_class"); - String tablename = rs.getString("topia_table"); - - String sql = MessageFormat.format(SQL.getProperty(SQL_ROLLBACK_DATA), tablename); - PreparedStatement sta = conn.prepareStatement(sql); - try{ - sta.setLong(1, context.getTransaction().getId()); - sta.execute(); - } finally { - sta.close(); + Connection conn = getConnection(); + try{ + String allTableSql = MessageFormat.format(SQL.getProperty(SQL_LOAD_ALL), "topia_mapping_table"); + PreparedStatement allTable = conn.prepareStatement(allTableSql); + ResultSet rs = allTable.executeQuery(); + while (rs.next()){ + String classname = rs.getString("topia_class"); + String tablename = rs.getString("topia_table"); + + String sql = MessageFormat.format(SQL.getProperty(SQL_ROLLBACK_DATA), tablename); + PreparedStatement sta = conn.prepareStatement(sql); + try{ + sta.setLong(1, context.getTransaction().getId()); + sta.execute(); + } finally { + sta.close(); + } } + conn.commit(); + } finally { + conn.close(); } - conn.commit(); - } finally { - conn.close(); + // creation d'un nouvelle transation + context.setTransaction(context.getTransaction().regenerateTransaction()); + // peut-etre faire quelque chose comme dans beginTransaction ? + } catch(SQLException eee){ + throw new TopiaPersistenceException("Erreur durant le rollback transaction: " + context.getTransaction().getId(), eee); } - // creation d'un nouvelle transation - context.setTransaction(context.getTransaction().regenerateTransaction()); - // peut-etre faire quelque chose comme dans beginTransaction ? - } catch(SQLException eee){ - throw new TopiaPersistenceException("Erreur durant le rollback transaction: " + context.getTransaction().getId(), eee); + } finally { + CallAnalyse.exit(PersistenceStorageJDBCMultiTable.class.getName() + ".rollbackTransaction"); } } @@ -1113,6 +1310,8 @@ * leve l'exception UnsupportedOperationException */ public List find(TopiaContext context, TopiaQuery query) throws TopiaPersistenceException { + try{ + CallAnalyse.enter(PersistenceStorageJDBCMultiTable.class.getName() + ".find"); // FIXME a refaire entierement avec un TopiaJDBCMultiTableQueryHelper // TopiaJDBCMultiTableQueryHelper queryHelper = new TopiaJDBCMultiTableQueryHelper(); // try { @@ -1163,14 +1362,22 @@ // } // return results; return null; + } finally { + CallAnalyse.exit(PersistenceStorageJDBCMultiTable.class.getName() + ".find"); + } } /** * Retourne l'historique de l'objet ayant l'id passé en paramètre */ public List getHistory(TopiaContext context, String id) throws TopiaPersistenceException { - // TODO - return new ArrayList(); + try{ + CallAnalyse.enter(PersistenceStorageJDBCMultiTable.class.getName() + ".getHistory"); + // TODO + return new ArrayList(); + } finally { + CallAnalyse.exit(PersistenceStorageJDBCMultiTable.class.getName() + ".getHistory"); + } } /** @@ -1180,6 +1387,8 @@ * les entités. */ public void cleanHistory(int depth) throws TopiaPersistenceException { + try{ + CallAnalyse.enter(PersistenceStorageJDBCMultiTable.class.getName() + ".cleanHistory"); // TODO // Pour tous les objets plus vieux que la derniere transaction // - supprimer tous les objets effacés @@ -1195,42 +1404,51 @@ // // exemple de requete: REMOVE_OLD(id, date) // delete from management where id=rs.id and date > 0 and date < rs.longdate; + } finally { + CallAnalyse.exit(PersistenceStorageJDBCMultiTable.class.getName() + ".cleanHistory"); + } } /** * Permet de savoir si un id existe encore dans le context de la transaction */ public boolean exists(TopiaContext context, String id) throws TopiaPersistenceException { - boolean result = false; try{ - Connection conn = getConnection(); + CallAnalyse.enter(PersistenceStorageJDBCMultiTable.class.getName() + ".exists"); + boolean result = false; try{ - Class clazz = TopiaId.getClassName(id); - String tablename = getTableName(clazz); - - String query = MessageFormat.format(SQL.getProperty(SQL_LOAD_HISTORY), tablename); - query = Util.setAllMultipleIds(query, context.getTransaction()); - PreparedStatement sta = conn.prepareStatement(query); + Connection conn = getConnection(); try{ - sta.setString(1, id); - sta.setLong(2, -context.getTransaction().getId()); - ResultSet rr = sta.executeQuery(); - if(rr.next()){ - result = !rr.getBoolean("topia_isDeleted"); - } + result = getLastLongdate(conn, context, new TopiaPersistenceObject(id)) != 0; + // Class clazz = TopiaId.getClassName(id); + // String tablename = getTableName(clazz); + + // String query = MessageFormat.format(SQL.getProperty(SQL_LOAD_HISTORY), tablename); + // query = Util.setAllMultipleIds(query, context.getTransaction()); + // PreparedStatement sta = conn.prepareStatement(query); + // try{ + // sta.setString(1, id); + // sta.setLong(2, -context.getTransaction().getId()); + // ResultSet rr = sta.executeQuery(); + // if(rr.next()){ + // result = !rr.getBoolean("topia_isDeleted"); + // } + // } finally { + // sta.close(); + // } + // conn.commit(); } finally { - sta.close(); + conn.close(); } - conn.commit(); - } finally { - conn.close(); + // } catch(TopiaNotFoundException eee){ + // throw new TopiaPersistenceException("Impossible de retrouver la classe de l'identifiant: " + id, eee); + } catch(SQLException eee){ + throw new TopiaPersistenceException("Erreur durant le test d'existance de l'entite: " + id, eee); } - } catch(TopiaNotFoundException eee){ - throw new TopiaPersistenceException("Impossible de retrouver la classe de l'identifiant: " + id, eee); - } catch(SQLException eee){ - throw new TopiaPersistenceException("Erreur durant le test d'existance de l'entite: " + id, eee); + return result; + } finally { + CallAnalyse.exit(PersistenceStorageJDBCMultiTable.class.getName() + ".exists"); } - return result; } } // PersistenceStorageJDBCMultiTable Index: topia/src/java/org/codelutin/topia/persistence/TopiaPersistenceProxy.java diff -u topia/src/java/org/codelutin/topia/persistence/TopiaPersistenceProxy.java:1.9 topia/src/java/org/codelutin/topia/persistence/TopiaPersistenceProxy.java:1.10 --- topia/src/java/org/codelutin/topia/persistence/TopiaPersistenceProxy.java:1.9 Fri Aug 26 17:53:35 2005 +++ topia/src/java/org/codelutin/topia/persistence/TopiaPersistenceProxy.java Tue Aug 30 13:19:53 2005 @@ -23,9 +23,9 @@ * Created: 16 juillet 2005 23:52:35 CEST * * @author Benjamin POUSSIN -* @version $Revision: 1.9 $ +* @version $Revision: 1.10 $ * -* Last update: $Date: 2005/08/26 17:53:35 $ +* Last update: $Date: 2005/08/30 13:19:53 $ * by : $Author: bpoussin $ */ @@ -50,6 +50,7 @@ import org.codelutin.topia.annotation.MethodInfoHelper; import org.codelutin.topia.annotation.MethodType; import org.codelutin.topia.EntitiesHelper; +import org.codelutin.topia.TopiaAssociationEntity; import org.codelutin.topia.TopiaEntity; import org.codelutin.topia.TopiaEntityOperation; import org.codelutin.topia.TopiaException; @@ -181,6 +182,7 @@ protected void setFieldAssociationCardinality1( TopiaPersistenceService assoPS, + boolean thisIsA, // indique si thisField represente la party A String thisField, String otherField, TopiaEntity entity, @@ -209,7 +211,7 @@ } } - TopiaEntity r = null; + TopiaAssociationEntity r = null; //On veut faire un entity.setXXX(value) // if(assoPS.getEntityClass() != entity.getEntityClass()){ // recuperation de l'objet a modifier s'il existe @@ -218,19 +220,30 @@ .addArg(entity); List col = ph.find(query); if(col.size() > 0){ - r = col.get(0); + r = (TopiaAssociationEntity)col.get(0); } // r = (TopiaEntity)MethodUtils.invokeMethod( // assoPS, // "findBy" + StringUtils.capitalize(otherField), // entity); if(r == null){ - r = assoPS.create(); - MethodUtils.invokeMethod(r, - "set" + StringUtils.capitalize(otherField), entity); + r = (TopiaAssociationEntity)assoPS.create(); + if(thisIsA){ + r.set_attribute_B_(entity); + } else { + r.set_attribute_A_(entity); + } + // MethodUtils.invokeMethod(r, + // "set" + StringUtils.capitalize(otherField), entity); + } + if(thisIsA){ + r.set_attribute_A_(value); + } else { + r.set_attribute_B_(value); } - MethodUtils.invokeMethod(r, - "set" + StringUtils.capitalize(thisField), value); + // MethodUtils.invokeMethod(r, + // "set" + StringUtils.capitalize(thisField), value); + // } else { // r = entity; // setField(thisField, value); @@ -245,19 +258,20 @@ protected void addFieldAssociationCardinalityN( TopiaPersistenceService assoPS, + boolean thisIsA, // indique si thisField represente la party A String thisField, String otherField, TopiaEntity entity, TopiaEntity value, boolean isAnyToOne) throws Exception { - TopiaEntity r = null; + TopiaAssociationEntity r = null; if(isAnyToOne){ TopiaQuery query = assoPS.newQuery() .where(thisField+"=? and "+otherField+"=?") .addArg(value).addArg(entity); List col = ph.find(query); if(col.size() > 0){ - r = col.get(0); + r = (TopiaAssociationEntity)col.get(0); } // Object[] args = new Object[2]; // if(thisField.compareTo(otherField) < 0){ @@ -273,23 +287,41 @@ //TODO A tester dans le cas où la classe d'assoc existe en BD !, // BB je pense que c fait, donc supprimer le TODO if(r == null){ - r = assoPS.create(); - MethodUtils.invokeMethod(r, - "set" + StringUtils.capitalize(otherField), entity); + r = (TopiaAssociationEntity)assoPS.create(); + if(thisIsA){ + r.set_attribute_B_(entity); + } else { + r.set_attribute_A_(entity); + } + + // MethodUtils.invokeMethod(r, + // "set" + StringUtils.capitalize(otherField), entity); + } + if(thisIsA){ + r.set_attribute_A_(value); + } else { + r.set_attribute_B_(value); } - MethodUtils.invokeMethod(r, - "set" + StringUtils.capitalize(thisField), value); + // MethodUtils.invokeMethod(r, + // "set" + StringUtils.capitalize(thisField), value); } else { TopiaQuery query = assoPS.newQuery() .where(thisField+"=? and "+otherField+"=?") .addArg(value).addArg(entity); if(ph.size(query) == 0){ // n'existe pas encore, donc on cree la relation - r = assoPS.create(); - MethodUtils.invokeMethod(r, - "set" + StringUtils.capitalize(otherField), entity); - MethodUtils.invokeMethod(r, - "set" + StringUtils.capitalize(thisField), value); + r = (TopiaAssociationEntity)assoPS.create(); + if(thisIsA){ + r.set_attribute_A_(value); + r.set_attribute_B_(entity); + } else { + r.set_attribute_A_(entity); + r.set_attribute_B_(value); + } + // MethodUtils.invokeMethod(r, + // "set" + StringUtils.capitalize(otherField), entity); + // MethodUtils.invokeMethod(r, + // "set" + StringUtils.capitalize(thisField), value); } } //TODO @@ -476,7 +508,7 @@ if(thisCardinality[1] == 1){ if(MethodInfoHelper.isFieldModifier(method)){ setFieldAssociationCardinality1( - assoPS, thisField, otherField, entity, + assoPS, partyA, thisField, otherField, entity, (TopiaEntity)args[0], otherCardinality[1] == 1); return null; } else { @@ -487,7 +519,7 @@ if(MethodInfoHelper.isFieldModifier(method)){ if(methodName.startsWith("add")){ addFieldAssociationCardinalityN( - assoPS, thisField, otherField, entity, + assoPS, partyA, thisField, otherField, entity, (TopiaEntity)args[0], otherCardinality[1] == 1); return null; } else if(methodName.startsWith("remove")){