Index: topia/src/java/org/codelutin/topia/persistence/PersistenceStorageJDBC.java diff -u topia/src/java/org/codelutin/topia/persistence/PersistenceStorageJDBC.java:1.1 topia/src/java/org/codelutin/topia/persistence/PersistenceStorageJDBC.java:1.2 --- topia/src/java/org/codelutin/topia/persistence/PersistenceStorageJDBC.java:1.1 Thu Jul 21 16:51:39 2005 +++ topia/src/java/org/codelutin/topia/persistence/PersistenceStorageJDBC.java Fri Jul 22 16:52:46 2005 @@ -23,14 +23,21 @@ * Created: 20 juillet 2005 15:25:06 CEST * * @author Benjamin POUSSIN - * @version $Revision: 1.1 $ + * @version $Revision: 1.2 $ * - * Last update: $Date: 2005/07/21 16:51:39 $ + * Last update: $Date: 2005/07/22 16:52:46 $ * by : $Author: bpoussin $ */ package org.codelutin.topia.persistence; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.UnsupportedEncodingException; +import java.lang.NoSuchMethodException; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; @@ -38,10 +45,13 @@ import java.sql.SQLException; import java.util.ArrayList; import java.util.Collection; +import java.util.HashMap; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; +import java.util.Map; import java.util.Properties; +import org.apache.commons.beanutils.MethodUtils; import org.apache.commons.dbcp.ConnectionFactory; import org.apache.commons.dbcp.DriverManagerConnectionFactory; import org.apache.commons.dbcp.PoolableConnectionFactory; @@ -62,6 +72,10 @@ *
  • persistence.storage.jdbc.url *
  • persistence.storage.jdbc.login *
  • persistence.storage.jdbc.password +* @todo peut-etre a l'instanciation faire un peu de menage dans la base, +* en supprimant tous les objets de transaction (date negative), car si le +* storage demarre, cela doit vouloir dire que l'appli c planté, ou que des +* transations, non pas ete commiter/rollbacker avant de quitter. */ public class PersistenceStorageJDBC implements PersistenceStorage { // PersistenceStorageJDBC @@ -70,7 +84,7 @@ static private final String TABLE_MANAGEMENT = "management"; static private final String TABLE_MANAGEMENT_FIELD_ID = "id"; - static private final String TABLE_MANAGEMENT_FIELD_DATE = "date"; + static private final String TABLE_MANAGEMENT_FIELD_DATE = "longdate"; static private final String TABLE_MANAGEMENT_FIELD_CLASS = "class"; static private final String TABLE_MANAGEMENT_FIELD_ISNEW = "isNew"; static private final String TABLE_MANAGEMENT_FIELD_ISDELETED = "isDeleted"; @@ -78,29 +92,111 @@ static private final String TABLE_DATA = "data"; static private final String TABLE_DATA_FIELD_ID = "id"; - static private final String TABLE_DATA_FIELD_DATE = "date"; + static private final String TABLE_DATA_FIELD_DATE = "longdate"; static private final String TABLE_DATA_FIELD_FIELD = "field"; static private final String TABLE_DATA_FIELD_VALUE = "value"; + protected Properties SQL = null; + static private Properties SQL_DEFAULT = new Properties(); + static private Properties SQL_POSTGRESQL = new Properties(SQL_DEFAULT); + static private Properties SQL_MYSQL = new Properties(SQL_DEFAULT); + static private Properties SQL_MCKOI = new Properties(SQL_DEFAULT); + static private Properties SQL_ORACLE = new Properties(SQL_DEFAULT); + + // byte[] postgresql bytea, mysql LONGBLOB, mckoi LONGVARBINARY (voirJAVA_OBJECT) + // string postgresql text, mysql text, mckoi text + // long postgresql bigint, mysql bigint, mckoi bigint + // boolean postgresql boolean, mysql boolean, mckoi boolean + static private final String SQL_CREATE_TABLE_MANAGEMENT = "SQL_CREATE_TABLE_MANAGEMENT"; + static private final String SQL_CREATE_TABLE_DATA = "SQL_CREATE_TABLE_DATA"; + static private final String SQL_CREATE_INDEX_MANAGEMENT_ID = "SQL_CREATE_INDEX_MANAGEMENT_ID"; + static private final String SQL_CREATE_INDEX_DATA_ID = "SQL_CREATE_INDEX_DATA_ID"; + static private final String SQL_CREATE_INDEX_MANAGEMENT_DATE = "SQL_CREATE_INDEX_MANAGEMENT_DATE"; + static private final String SQL_CREATE_INDEX_DATA_DATE = "SQL_CREATE_INDEX_DATA_DATE"; + + static private final String SQL_TABLE_EXISTS = "SQL_TABLE_EXISTS"; + /** charge tous les management existant pour un id, tri de facon a avoir * la version la plus recente en premier dans le ResultSet. Le premier * est celui de la transaction s'il exist sinon celui qui a la date la * plus elevé mais ne depassant pas la transaction */ - static private final String SQL_LOAD_HISTORY = "SELECT * FROM " + TABLE_MANAGEMENT + " WHERE id=? AND ((date > 0 and date<=?) or date=?) order by abs(date) desc;"; + static private final String SQL_LOAD_HISTORY = "SQL_LOAD_HISTORY"; /** supprime les données de la table data */ - static private final String SQL_REMOVE_DATA = "DELETE " + TABLE_DATA + " WHERE id=? and date=?"; + 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 = "SELECT DISTINCT(id) FROM " + TABLE_MANAGEMENT + " WHERE (date=? OR (date>0 AND date<=?)) AND id NOT IN (SELECT id FROM " + TABLE_MANAGEMENT + " WHERE (date=? OR (date>0 AND date<=?)) AND isDeleted=true);"; - static private final String SQL_INSERT_DATA = "INSERT INTO " + TABLE_DATA + " VALUES (?, ?, ?, ?);"; - static private final String SQL_INSERT_MANAGEMENT = "INSERT INTO " + TABLE_MANAGEMENT + " VALUES (?, ?, ?, ?, ?, ?);"; - static private final String SQL_LOAD_DATA = "SELECT * FROM " + TABLE_DATA + " WHERE id=? AND date=?"; - static private final String SQL_LOAD_MANAGEMENT = "SELECT * FROM " + TABLE_MANAGEMENT + " WHERE id=? AND date=?"; - static private final String SQL_UPDATE_DATA = "UPDATE " + TABLE_DATA + " SET value=? WHERE id=? AND date=? AND filed=?;"; - static private final String SQL_UPDATE_SCHEMAVERSION = "UPDATE " + TABLE_MANAGEMENT + " SET schemaVersion=? WHERE id=? AND date=?;"; - static private final String SQL_ROLLBACK_MANAGEMENT = "DELETE " + TABLE_MANAGEMENT + " WHERE date=?"; - static private final String SQL_ROLLBACK_DATA = "DELETE " + TABLE_DATA + " WHERE date=?"; - static private final String SQL_COMMIT_MANAGEMENT = "UODATE " + TABLE_MANAGEMENT + "SET date=? WHERE date=?"; - static private final String SQL_COMMIT_DATA = "UODATE " + TABLE_DATA + "SET date=? WHERE date=?"; + static private final String SQL_GET_ALL_ID = "SQL_GET_ALL_ID"; + static private final String SQL_INSERT_DATA = "SQL_INSERT_DATA"; + static private final String SQL_INSERT_MANAGEMENT = "SQL_INSERT_MANAGEMENT"; + static private final String SQL_LOAD_DATA = "SQL_LOAD_DATA"; + static private final String SQL_LOAD_MANAGEMENT = "SQL_LOAD_MANAGEMENT"; + static private final String SQL_UPDATE_DATA = "SQL_UPDATE_DATA"; + static private final String SQL_UPDATE_MANAGEMENT = "SQL_UPDATE_MANAGEMENT"; + static private final String SQL_UPDATE_SCHEMAVERSION = "SQL_UPDATE_SCHEMAVERSION"; + static private final String SQL_ROLLBACK_MANAGEMENT = "SQL_ROLLBACK_MANAGEMENT"; + static private final String SQL_ROLLBACK_DATA = "SQL_ROLLBACK_DATA"; + static private final String SQL_COMMIT_MANAGEMENT = "SQL_COMMIT_MANAGEMENT"; + static private final String SQL_COMMIT_DATA = "SQL_COMMIT_DATA"; + + static { + SQL_DEFAULT.put(SQL_TABLE_EXISTS, + "SELECT count(*) FROM management where id='' AND longdate=0;"); + SQL_DEFAULT.put(SQL_CREATE_TABLE_MANAGEMENT, + "CREATE TABLE management (id text, longdate bigint, class text, isNew boolean, isDeleted boolean, schemaVersion bigint, PRIMARY KEY (id, longdate));"); + SQL_DEFAULT.put(SQL_CREATE_TABLE_DATA, + "CREATE TABLE data (id text, longdate bigint, field text, value bytea, type text, PRIMARY KEY (id, longdate, field));"); + SQL_DEFAULT.put(SQL_CREATE_INDEX_MANAGEMENT_ID, + "CREATE INDEX index_management_id ON management (id);"); + SQL_DEFAULT.put(SQL_CREATE_INDEX_MANAGEMENT_DATE, + "CREATE INDEX index_management_llongdate ON management (longdate);"); + SQL_DEFAULT.put(SQL_CREATE_INDEX_DATA_ID, + "CREATE INDEX index_data_id ON data (id);"); + SQL_DEFAULT.put(SQL_CREATE_INDEX_DATA_DATE, + "CREATE INDEX index_data_longdate ON data (longdate);"); + SQL_DEFAULT.put(SQL_LOAD_HISTORY, + "SELECT * FROM management WHERE id=? AND ((longdate > 0 and longdate<=?) or longdate=?) order by abs(longdate) desc;"); + SQL_DEFAULT.put(SQL_REMOVE_DATA, + "DELETE data WHERE id=? and longdate=?;"); + SQL_DEFAULT.put(SQL_GET_ALL_ID, + "SELECT DISTINCT(id) FROM management WHERE (longdate=? OR (longdate>0 AND longdate<=?)) AND id NOT IN (SELECT id FROM management WHERE (longdate=? OR (longdate>0 AND longdate<=?)) AND isDeleted=true);"); + SQL_DEFAULT.put(SQL_INSERT_DATA, + "INSERT INTO data VALUES (?, ?, ?, ?, ?);"); + SQL_DEFAULT.put(SQL_INSERT_MANAGEMENT, + "INSERT INTO management VALUES (?, ?, ?, ?, ?, ?);"); + SQL_DEFAULT.put(SQL_LOAD_DATA, + "SELECT * FROM data WHERE id=? AND longdate=?"); + SQL_DEFAULT.put(SQL_LOAD_MANAGEMENT, + "SELECT * FROM management WHERE id=? AND longdate=?"); + SQL_DEFAULT.put(SQL_UPDATE_DATA, + "UPDATE data SET value=?, type=? WHERE id=? AND longdate=? AND field=?;"); + SQL_DEFAULT.put(SQL_UPDATE_MANAGEMENT, + "UPDATE management SET isDeleted=? WHERE id=? AND longdate=?;"); + SQL_DEFAULT.put(SQL_UPDATE_SCHEMAVERSION, + "UPDATE management SET schemaVersion=? WHERE id=? AND longdate=?;"); + SQL_DEFAULT.put(SQL_ROLLBACK_MANAGEMENT, + "DELETE FROM management WHERE longdate=?;"); + SQL_DEFAULT.put(SQL_ROLLBACK_DATA, + "DELETE FROM data WHERE longdate=?;"); + SQL_DEFAULT.put(SQL_COMMIT_MANAGEMENT, + "UPDATE management SET longdate=? WHERE longdate=?;"); + SQL_DEFAULT.put(SQL_COMMIT_DATA, + "UPDATE data SET longdate=? WHERE longdate=?;"); + + SQL_MYSQL.setProperty(SQL_CREATE_TABLE_MANAGEMENT, + "CREATE TABLE management (id varchar(100), longdate bigint, class text, isNew bool, isDeleted bool, schemaVersion bigint, PRIMARY KEY (id, longdate));"); + SQL_MYSQL.put(SQL_CREATE_TABLE_DATA, + "CREATE TABLE data (id varchar(100), longdate bigint, field varchar(100), value longblob, type text, PRIMARY KEY (id, longdate, field));"); + + SQL_MCKOI.setProperty(SQL_CREATE_TABLE_DATA, + "CREATE TABLE data (id text, longdate bigint, field text, value longvarbinary, type text, PRIMARY KEY (id, longdate, field));"); + + SQL_ORACLE.setProperty(SQL_CREATE_TABLE_MANAGEMENT, + "CREATE TABLE management (id varchar(100), longdate number(21), class varchar(255), isNew number(1), isDeleted number(1), schemaVersion number(21), PRIMARY KEY (id, longdate));"); + SQL_ORACLE.put(SQL_CREATE_TABLE_DATA, + "CREATE TABLE data (id varchar(100), longdate number(21), field varchar(100), value blob, type varchar(255), PRIMARY KEY (id, longdate, field));"); + + } + + protected Properties properties = null; protected DriverManagerConnectionFactory connectionPool = null; @@ -112,6 +208,17 @@ 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 { + SQL = SQL_POSTGRESQL; + } + + Util.getClazz(driver); + + GenericObjectPool connectionPool = new GenericObjectPool(null); ConnectionFactory connectionFactory = new DriverManagerConnectionFactory(url, login, password); @@ -122,54 +229,176 @@ statementPool, null, false, false); PoolingDriver poolDriver = new PoolingDriver(); poolDriver.registerPool("topia",connectionPool); + + if(!tableExists()){ + createTable(); + } } protected Connection getConnection() throws SQLException { return DriverManager.getConnection("jdbc:apache:commons:dbcp:topia"); } - /** - * Demande la sauvegarde de l'entité dans le context de la transaction - */ - public void store(TopiaTransaction tt, TopiaPersistenceObject tpo) throws TopiaPersistenceException { + protected boolean tableExists() { + boolean result = false; try{ - Connection conn = getConnection(); - PreparedStatement sta = conn.prepareStatement(SQL_LOAD_MANAGEMENT); + Connection conn = getConnection(); + try{ + PreparedStatement sta = null; + sta = conn.prepareStatement(SQL.getProperty(SQL_TABLE_EXISTS)); + sta.execute(); + sta.close(); + } finally { + conn.close(); + } + result = true; + }catch(SQLException eee){ + log.log(Level.INFO, "Table don't exist"); + result =false; + } + return result; + } + + + protected void createTable() throws TopiaPersistenceException { try{ - sta.setString(1, tpo.getManagement().getId()); - sta.setLong(2, tt.getId()); - ResultSet rr = sta.executeQuery(); - // si l'objet n'etait pas encore dans la transaction, on le met - tpo.getManagement().setDate(tt.getId()); - if(rr.next()){ - // l'objet existait on le met a jour - rr.updateBoolean("isDeleted", tpo.getManagement().isDeleted()); - rr.updateLong("date", tpo.getManagement().getDate()); - saveData(conn, tt, tpo, false); - } else { - // l'objet n'existait pas, on le creer - PreparedStatement insert = conn.prepareStatement(SQL_INSERT_MANAGEMENT); + Connection conn = getConnection(); + try{ + PreparedStatement sta = null; + sta = conn.prepareStatement(SQL.getProperty(SQL_CREATE_TABLE_MANAGEMENT)); + sta.execute(); + sta.close(); + + sta = conn.prepareStatement(SQL.getProperty(SQL_CREATE_TABLE_DATA)); + sta.execute(); + sta.close(); + + sta = conn.prepareStatement(SQL.getProperty(SQL_CREATE_INDEX_MANAGEMENT_ID)); + sta.execute(); + sta.close(); + + sta = conn.prepareStatement(SQL.getProperty(SQL_CREATE_INDEX_DATA_ID)); + sta.execute(); + sta.close(); + + sta = conn.prepareStatement(SQL.getProperty(SQL_CREATE_INDEX_MANAGEMENT_DATE)); + sta.execute(); + sta.close(); + + sta = conn.prepareStatement(SQL.getProperty(SQL_CREATE_INDEX_DATA_DATE)); + sta.execute(); + sta.close(); + + conn.commit(); + } finally { + conn.close(); + } + }catch(SQLException eee){ + throw new TopiaPersistenceException("Erreur de creation des tables", eee); + } + } + + 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; + + public void store(TopiaTransaction tt, Collection tpos) throws TopiaPersistenceException { + long time = System.currentTimeMillis(); + Connection conn = null; + try{ + conn = getConnection(); + try{ + for(TopiaPersistenceObject tpo: tpos){ + store(conn, tt, tpo); + } + } finally { + conn.commit(); + conn.close(); + } + } catch(SQLException eee) { + if(conn != null){ try{ - insert.setString(1, tpo.getManagement().getId()); - insert.setLong(2, tpo.getManagement().getDate()); - insert.setString(3, TopiaId.getClassNameAsString(tpo.getManagement().getId())); - insert.setBoolean(4, tpo.getManagement().isNew()); - insert.setBoolean(5, tpo.getManagement().isDeleted()); - insert.setLong(6, tpo.getManagement().getSchemaVersion()); - insert.execute(); - } finally { - insert.close(); + conn.rollback(); + conn.close(); + } + catch(SQLException zzz){ + log.log(Level.INFO, "Erreur durant le rollback du a une exception", zzz); } - saveData(conn, tt, tpo, true); } - } finally { - sta.close(); + throw new TopiaPersistenceException("Erreur durant la sauvegarde de la liste d'entites", eee); } - conn.commit(); - conn.close(); + time_storeList += System.currentTimeMillis() - time; + } + + public void store(TopiaTransaction tt, TopiaPersistenceObject tpo) throws TopiaPersistenceException { + long time = System.currentTimeMillis(); + Connection conn = null; + try{ + conn = getConnection(); + try{ + store(conn, tt, tpo); + } finally { + conn.commit(); + conn.close(); + } } catch(SQLException eee) { + if(conn != null){ + try{ + conn.rollback(); + conn.close(); + } + catch(SQLException zzz){ + log.log(Level.INFO, "Erreur durant le rollback du a une exception", zzz); + } + } throw new TopiaPersistenceException("Erreur durant la sauvegarde de l'entite: " + tpo.getManagement().getId(), eee); } + time_storeOne += System.currentTimeMillis() - time; + } + + /** + * Demande la sauvegarde de l'entité dans le context de la transaction + */ + public void store(Connection conn, TopiaTransaction tt, TopiaPersistenceObject tpo) + throws SQLException, TopiaPersistenceException { + long time = System.currentTimeMillis(); + // si l'objet n'etait pas encore dans la transaction, on le met + tpo.getManagement().setDate(tt.getId()); + + boolean exists = managementExists(conn, tt, tpo); + + if(exists){ + // l'objet existait on le met a jour + saveManagement(conn, tt, tpo, false); + saveData(conn, tt, tpo, false); + } else { + // l'objet n'existait pas, on le creer + saveManagement(conn, tt, tpo, true); + saveData(conn, tt, tpo, true); + } + time_store += System.currentTimeMillis() - time; + } + + protected boolean managementExists(Connection conn, TopiaTransaction tt, + TopiaPersistenceObject tpo) throws SQLException, TopiaPersistenceException { + long time = System.currentTimeMillis(); + boolean result = false; + PreparedStatement sta = conn.prepareStatement(SQL.getProperty(SQL_LOAD_MANAGEMENT)); + try{ + sta.setString(1, tpo.getManagement().getId()); + sta.setLong(2, tpo.getManagement().getDate()); + ResultSet rr = sta.executeQuery(); + result = rr.next(); + } finally { + sta.close(); + } + time_managementExists += System.currentTimeMillis() - time; + return result; } /** @@ -183,7 +412,7 @@ try{ Connection conn = getConnection(); try{ - PreparedStatement sta = conn.prepareStatement(SQL_LOAD_MANAGEMENT); + PreparedStatement sta = conn.prepareStatement(SQL.getProperty(SQL_LOAD_MANAGEMENT)); try{ sta.setString(1, tpo.getManagement().getId()); sta.setLong(2, tt.getId()); @@ -193,12 +422,10 @@ // transaction on recherche le plus recent des objet // commit pour cette transaction sta.close(); - sta = conn.prepareStatement(SQL_LOAD_HISTORY); + sta = conn.prepareStatement(SQL.getProperty(SQL_LOAD_HISTORY)); sta.setString(1, tpo.getManagement().getId()); - sta.setLong(2, tt.getId()); - sta.setLong(3, -tt.getId()); - sta.setLong(4, tt.getId()); - sta.setLong(5, -tt.getId()); + sta.setLong(2, -tt.getId()); + sta.setLong(3, tt.getId()); management = sta.executeQuery(); if(!management.next()){ // on a pas trouvé d'objet sattisfaisant la demande @@ -210,7 +437,7 @@ long storedSchemaVersion = management.getLong("schemaVersion"); if(tpo.getManagement().isUnloaded()){ - tpo.getManagement().setDate(management.getLong("date")); + tpo.getManagement().setDate(management.getLong("longdate")); tpo.getManagement().setStored(true); tpo.getManagement().setDeleted(management.getBoolean("isDeleted")); // l'objet quoi qu'il arrive ne sera plus nouveau @@ -232,7 +459,7 @@ // on commence par supprimer toutes les anciennes // car des champs on pu disparaitre et d'autre apparaitre - PreparedStatement delete = conn.prepareStatement(SQL_REMOVE_DATA); + PreparedStatement delete = conn.prepareStatement(SQL.getProperty(SQL_REMOVE_DATA)); delete.setString(1, tpo.getManagement().getId()); delete.setLong(2, tpo.getManagement().getDate()); delete.execute(); @@ -242,7 +469,7 @@ saveData(conn, tt, tpo, true); // on change le numero de schema des données - PreparedStatement updateSchema = conn.prepareStatement(SQL_UPDATE_SCHEMAVERSION); + PreparedStatement updateSchema = conn.prepareStatement(SQL.getProperty(SQL_UPDATE_SCHEMAVERSION)); try{ updateSchema.setLong(1, tpo.getManagement().getSchemaVersion()); updateSchema.setString(2, tpo.getManagement().getId()); @@ -260,8 +487,8 @@ } finally { sta.close(); } - } finally { conn.commit(); + } finally { conn.close(); } } catch(SQLException eee) { @@ -286,6 +513,63 @@ return data; } + protected byte[] objectToDatabase(String type, Object value) throws TopiaPersistenceException { + long time = System.currentTimeMillis(); + byte[] result; + try{ + if(value instanceof Number + || value instanceof String + || value instanceof Character + || value instanceof Boolean){ + try{ + result = (""+value).getBytes("UTF-8"); + }catch(UnsupportedEncodingException eee){ + throw new TopiaPersistenceException("Can't convert String to bytes array for database storage: " + type, eee); + } + } else { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(baos); + oos.writeObject(value); + baos.close(); + result = baos.toByteArray(); + } + }catch(Exception eee){ + throw new TopiaPersistenceException("Can't convert objet to bytes array: " + type, eee); + } + time_objectToDatabase += System.currentTimeMillis() - time; + return result; + } + + protected Object databaseToObject(String type, byte[] value) throws TopiaPersistenceException { + long time = System.currentTimeMillis(); + Object result; + try{ + Class clazz = Util.getClazz(type); + if(Number.class.isAssignableFrom(clazz) + || String.class.equals(clazz) + || Character.class.equals(clazz) + || Boolean.class.equals(clazz)){ + String stringResult = new String(value, "UTF-8"); + if(Number.class.isAssignableFrom(clazz) || Boolean.class.equals(clazz)){ + result = clazz.getMethod("valueOf", String.class).invoke(null, stringResult); + } else if(Character.class.equals(clazz)) { + result = Character.valueOf(stringResult.charAt(0)); + } else { + result = stringResult; + } + } else { + ByteArrayInputStream bais = new ByteArrayInputStream(value); + ObjectInputStream ois = new ObjectInputStream(bais); + result = ois.readObject(); + bais.close(); + } + }catch(Exception eee){ + throw new TopiaPersistenceException("Can't convert bytes array to object: " + type, eee); + } + time_databaseToObject += System.currentTimeMillis() - time; + return result; + } + /** * Charge les champs demandé dans management.getAskedFields(). Si le champs * existe déja dans data, alors il n'est pas chargé meme s'il est demandé @@ -302,8 +586,8 @@ protected void loadData(Connection conn, TopiaTransaction tt, TopiaPersistenceObject tpo, TopiaPersistenceObjectData data, - boolean forceLoadAllField) throws SQLException { - PreparedStatement sta = conn.prepareStatement(SQL_LOAD_DATA); + boolean forceLoadAllField) throws SQLException, TopiaPersistenceException { + PreparedStatement sta = conn.prepareStatement(SQL.getProperty(SQL_LOAD_DATA)); try{ sta.setString(1, tpo.getManagement().getId()); sta.setLong(2, tpo.getManagement().getDate()); @@ -316,7 +600,9 @@ // avant le chargement des données if(forceLoadAllField || tpo.getAskedFields().contains(field)){ // on le charge que si on a besoin - Object value = rr.getObject("value"); + String type = rr.getString("type"); + byte[] bytesValue = rr.getBytes("value"); + Object value = databaseToObject(type, bytesValue); data.setField(field, value); // on vient de le charger, donc plus besoin de le faire tpo.getAskedFields().remove(field); @@ -328,34 +614,79 @@ } } + protected void saveManagement(Connection conn, TopiaTransaction tt, + TopiaPersistenceObject tpo, boolean forceInsert) + throws SQLException, TopiaPersistenceException { + long time = System.currentTimeMillis(); + if(forceInsert){ + PreparedStatement insert = conn.prepareStatement(SQL.getProperty(SQL_INSERT_MANAGEMENT)); + try{ + insert.setString(1, tpo.getManagement().getId()); + insert.setLong(2, tpo.getManagement().getDate()); + insert.setString(3, TopiaId.getClassNameAsString(tpo.getManagement().getId())); + insert.setBoolean(4, tpo.getManagement().isNew()); + insert.setBoolean(5, tpo.getManagement().isDeleted()); + insert.setLong(6, tpo.getManagement().getSchemaVersion()); + insert.execute(); + } finally { + insert.close(); + } + } else { + PreparedStatement insert = conn.prepareStatement(SQL.getProperty(SQL_UPDATE_MANAGEMENT)); + try{ + insert.setString(2, tpo.getManagement().getId()); + insert.setLong(3, tpo.getManagement().getDate()); + // insert.setString(1, TopiaId.getClassNameAsString(tpo.getManagement().getId())); + // insert.setBoolean(2, tpo.getManagement().isNew()); + insert.setBoolean(1, tpo.getManagement().isDeleted()); + // insert.setLong(4, tpo.getManagement().getSchemaVersion()); + insert.execute(); + } finally { + insert.close(); + } + } + time_saveManagement += System.currentTimeMillis() - time; + } + /** * Sauve tous les champs modifier et vide la liste des champs modifiée * @param forceInsert si vrai fait un insert, sinon fait un update */ protected void saveData(Connection conn, TopiaTransaction tt, - TopiaPersistenceObject tpo, boolean forceInsert) throws SQLException { + TopiaPersistenceObject tpo, boolean forceInsert) + throws SQLException, TopiaPersistenceException { + // TODO supprimer le time apres analyse des perfs + long time = System.currentTimeMillis(); synchronized(tpo.getModifiedFields()){ if(forceInsert){ - PreparedStatement insert = conn.prepareStatement(SQL_INSERT_DATA); + PreparedStatement insert = conn.prepareStatement(SQL.getProperty(SQL_INSERT_DATA)); try{ insert.setString(1, tpo.getManagement().getId()); insert.setLong(2, tpo.getManagement().getDate()); for(String field: tpo.getData().keySet()){ insert.setString(3, field); - insert.setObject(4, tpo.getData().get(field)); + Object value = tpo.getData().get(field); + String type = value.getClass().getName(); + byte[] bytesValue = objectToDatabase(type, value); + insert.setBytes(4, bytesValue); + insert.setString(5, type); insert.execute(); } } finally { insert.close(); } } else { - PreparedStatement update = conn.prepareStatement(SQL_UPDATE_DATA); + PreparedStatement update = conn.prepareStatement(SQL.getProperty(SQL_UPDATE_DATA)); try{ - update.setString(2, tpo.getManagement().getId()); - update.setLong(3, tpo.getManagement().getDate()); + update.setString(3, tpo.getManagement().getId()); + update.setLong(4, tpo.getManagement().getDate()); for(String field: tpo.getData().keySet()){ - update.setString(4, field); - update.setObject(1, tpo.getData().get(field)); + update.setString(5, field); + Object value = tpo.getData().get(field); + String type = value.getClass().getName(); + byte[] bytesValue = objectToDatabase(type, value); + update.setBytes(1, bytesValue); + update.setString(2, type); update.execute(); } } finally { @@ -364,6 +695,7 @@ } tpo.getModifiedFields().clear(); } + time_saveData += System.currentTimeMillis() - time; } /** @@ -375,7 +707,7 @@ try{ Connection conn = getConnection(); try{ - PreparedStatement sta = conn.prepareStatement(SQL_GET_ALL_ID); + PreparedStatement sta = conn.prepareStatement(SQL.getProperty(SQL_GET_ALL_ID)); try{ sta.setLong(1, tt.getId()); sta.setLong(2, -tt.getId()); @@ -402,7 +734,12 @@ * Permet d'indiquer au storage le debut d'une transaction */ public void beginTransaction(TopiaTransaction tt) throws TopiaPersistenceException { - // FIXME + // On pourrait conservé l'id de la transaction, et lors d'appel + // d'autre methode verifier que cet Id est bien l'id d'une transation + // qui a un beginTransaction. + // Mais normalement seul le framework utilise le storage, donc si + // tout est bien fait, il n'y a pas besoin de verifier, ce qui peut + // faire gagne un peu de temps. } /** @@ -420,7 +757,7 @@ TopiaTransaction newtt = tt.regenerateTransaction(); Connection conn = getConnection(); try{ - PreparedStatement sta = conn.prepareStatement(SQL_COMMIT_MANAGEMENT); + PreparedStatement sta = conn.prepareStatement(SQL.getProperty(SQL_COMMIT_MANAGEMENT)); try{ sta.setLong(1, -newtt.getId()); sta.setLong(2, tt.getId()); @@ -428,7 +765,7 @@ } finally { sta.close(); } - sta = conn.prepareStatement(SQL_COMMIT_DATA); + sta = conn.prepareStatement(SQL.getProperty(SQL_COMMIT_DATA)); try{ sta.setLong(1, -newtt.getId()); sta.setLong(2, tt.getId()); @@ -436,6 +773,7 @@ } finally { sta.close(); } + conn.commit(); } finally { conn.close(); } @@ -455,20 +793,21 @@ try{ Connection conn = getConnection(); try{ - PreparedStatement sta = conn.prepareStatement(SQL_ROLLBACK_MANAGEMENT); + PreparedStatement sta = conn.prepareStatement(SQL.getProperty(SQL_ROLLBACK_MANAGEMENT)); try{ sta.setLong(1, tt.getId()); sta.execute(); } finally { sta.close(); } - sta = conn.prepareStatement(SQL_ROLLBACK_DATA); + sta = conn.prepareStatement(SQL.getProperty(SQL_ROLLBACK_DATA)); try{ sta.setLong(1, tt.getId()); sta.execute(); } finally { sta.close(); } + conn.commit(); } finally { conn.close(); } @@ -525,13 +864,11 @@ try{ Connection conn = getConnection(); try{ - PreparedStatement sta = conn.prepareStatement(SQL_LOAD_HISTORY); + PreparedStatement sta = conn.prepareStatement(SQL.getProperty(SQL_LOAD_HISTORY)); try{ sta.setString(1, id); - sta.setLong(2, tt.getId()); - sta.setLong(3, -tt.getId()); - sta.setLong(4, tt.getId()); - sta.setLong(5, -tt.getId()); + sta.setLong(2, -tt.getId()); + sta.setLong(3, tt.getId()); ResultSet rr = sta.executeQuery(); if(rr.next()){ result = !rr.getBoolean("isDeleted"); Index: topia/src/java/org/codelutin/topia/persistence/TopiaTransactionHelper.java diff -u topia/src/java/org/codelutin/topia/persistence/TopiaTransactionHelper.java:1.2 topia/src/java/org/codelutin/topia/persistence/TopiaTransactionHelper.java:1.3 --- topia/src/java/org/codelutin/topia/persistence/TopiaTransactionHelper.java:1.2 Wed Jul 20 12:49:52 2005 +++ topia/src/java/org/codelutin/topia/persistence/TopiaTransactionHelper.java Fri Jul 22 16:52:46 2005 @@ -23,9 +23,9 @@ * Created: 16 juillet 2005 23:27:18 CEST * * @author Benjamin POUSSIN - * @version $Revision: 1.2 $ + * @version $Revision: 1.3 $ * - * Last update: $Date: 2005/07/20 12:49:52 $ + * Last update: $Date: 2005/07/22 16:52:46 $ * by : $Author: bpoussin $ */ @@ -33,13 +33,18 @@ import java.util.logging.Level; import java.util.logging.Logger; +import java.util.Properties; public class TopiaTransactionHelper { // TopiaTransactionHelper /** to use log facility, just put in your code: log.info(\"...\"); */ static private Logger log = Logger.getLogger("org.codelutin.topia.persistence.TopiaTransactionHelper"); - public TopiaTransactionHelper(){} + protected Properties properties = null; + + public TopiaTransactionHelper(Properties properties){ + this.properties = properties; + } public TopiaTransaction newTranstaction(){ return new TopiaTransaction(this);