Author: athimel Date: 2013-10-11 17:13:30 +0200 (Fri, 11 Oct 2013) New Revision: 2840 Url: http://nuiton.org/projects/topia/repository/revisions/2840 Log: Implementation Hibernate session open/commit/rollback/close Modified: trunk/topia-persistence/src/main/java/org/nuiton/topia/AbstractTopiaPersistenceContext.java trunk/topia-persistence/src/main/java/org/nuiton/topia/TopiaPersistenceContext.java trunk/topia-persistence/src/main/java/org/nuiton/topia/TopiaTransaction.java trunk/topia-persistence/src/main/java/org/nuiton/topia/event/TopiaTransactionEvent.java trunk/topia-persistence/src/main/java/org/nuiton/topia/framework/AbstractTopiaContext.java trunk/topia-persistence/src/main/java/org/nuiton/topia/framework/TopiaFiresSupport.java trunk/topia-service-migration/src/main/java/org/nuiton/topia/migration/TopiaMigrationEngine.java Modified: trunk/topia-persistence/src/main/java/org/nuiton/topia/AbstractTopiaPersistenceContext.java =================================================================== --- trunk/topia-persistence/src/main/java/org/nuiton/topia/AbstractTopiaPersistenceContext.java 2013-10-11 15:10:28 UTC (rev 2839) +++ trunk/topia-persistence/src/main/java/org/nuiton/topia/AbstractTopiaPersistenceContext.java 2013-10-11 15:13:30 UTC (rev 2840) @@ -24,28 +24,25 @@ * #L% */ -import com.google.common.base.Preconditions; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; +import java.lang.reflect.InvocationTargetException; +import java.util.Map; + import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.hibernate.FlushMode; import org.hibernate.HibernateException; import org.hibernate.Session; import org.hibernate.SessionFactory; +import org.hibernate.Transaction; import org.hibernate.cfg.Configuration; -import org.hibernate.tool.hbm2ddl.SchemaExport; -import org.hibernate.tool.hbm2ddl.SchemaUpdate; import org.nuiton.topia.framework.TopiaFiresSupport; -import org.nuiton.topia.framework.TopiaUtil; import org.nuiton.topia.persistence.AbstractTopiaDAO; import org.nuiton.topia.persistence.TopiaDAO; import org.nuiton.topia.persistence.TopiaEntity; import org.nuiton.topia.persistence.TopiaIdFactory; -import java.lang.reflect.InvocationTargetException; -import java.util.List; -import java.util.Map; -import java.util.Properties; +import com.google.common.base.Preconditions; +import com.google.common.collect.Maps; /** * Abstract implementation of the TopiaPersistenceContext. This class will be extended by a generated one in order to @@ -85,46 +82,46 @@ */ protected TopiaIdFactory topiaIdFactory; -// /** -// * Current context configuration -// */ -// protected Properties config; + protected boolean closed = false; /** * Creating a new TopiaPersistenceContext is equivalent to creating a new transaction * * @param hibernateProvider - * @param sqlSupport * @param listenableSupport - * @param topiaIdFactory -// * @param config + * @param topiaIdFactory // * @param config */ public AbstractTopiaPersistenceContext(HibernateProvider hibernateProvider, TopiaListenableSupport listenableSupport, TopiaIdFactory topiaIdFactory) { - this.hibernateSupport = new InternalTopiaHibernateSupport(hibernateProvider); + Session hibernateSession = startTransaction(hibernateProvider); + this.hibernateSupport = new InternalTopiaHibernateSupport(hibernateProvider, hibernateSession); // TODO brendan 11/10/13 init this.sqlSupport this.listenableSupport = listenableSupport; this.topiaIdFactory = topiaIdFactory; -// this.config = config; this.firesSupport = new TopiaFiresSupport(); this.jpaSupport = new HibernateTopiaJpaSupport(hibernateSupport, firesSupport); - } protected class InternalTopiaHibernateSupport implements TopiaHibernateSupport { protected HibernateProvider hibernateProvider; + protected Session hibernateSession; - protected InternalTopiaHibernateSupport(HibernateProvider hibernateProvider) { + protected InternalTopiaHibernateSupport(HibernateProvider hibernateProvider, Session hibernateSession) { this.hibernateProvider = hibernateProvider; + this.hibernateSession = hibernateSession; } + public void setHibernateSession(Session hibernateSession) { + this.hibernateSession = hibernateSession; + } + @Override public Session getHibernateSession() { - return null; + return hibernateSession; } @Override @@ -138,11 +135,51 @@ } } + protected Session startTransaction(HibernateProvider hibernateProvider) throws TopiaException { + + SessionFactory factory = hibernateProvider.getSessionFactory(); + Session result = factory.openSession(); + + // new TopiaInterceptor(result)); + // on ne synchronise jamais les données avec la base tant que + // l'utilisateur n'a pas fait de commit du context + result.setFlushMode(FlushMode.MANUAL); + + // tchemit 2010-12-06 propagates the value of the flag +// result.useFlushMode = useFlushMode; + + // 20060926 poussin ajouter pour voir si ca regle les problemes de + // deadlock h2. Conclusion, il faut bien ouvrir une transaction + // maintenant, sinon lorsque l'on fait des acces a la base, une + // transaction par defaut est utilisé mais elle n'est jamais vraiment + // fermé ce qui pose des problemes de lock sur les tables. + try { + result.beginTransaction(); + } catch (Exception eee) { + + // on a pas pu ouvrir la transaction, on faut donc tout fermer + // et declancher une exception + try { + result.close(); + } catch (HibernateException e1) { + if (log.isErrorEnabled()) { + log.error("Could not close hibernate session", e1); + } + } + + String message = String.format("An error occurs while asking a new transaction: %1$s", eee.getMessage()); + throw new TopiaException(message, eee); + } + + // fire event + getFiresSupport().fireOnBeginTransaction(this); + return result; + } + protected void checkClosed() throws TopiaException { - // TODO AThimel 27/09/13 IS it still useful ? -// if (closed) { -// throw new TopiaException("This context is closed, it is not possible to use it anymore"); -// } + if (closed) { + throw new TopiaException("This context is closed, it is not possible to use it anymore"); + } } protected TopiaFiresSupport getFiresSupport() { @@ -175,11 +212,6 @@ return topiaIdFactory; } -// @Override -// public Properties getConfig() { -// return config; -// } - @Override public <E extends TopiaEntity> TopiaDAO<E> getDAO(Class<E> entityClass) { Preconditions.checkArgument(entityClass != null, "The method 'getDAO' requires a non null 'entityClass' parameter"); @@ -245,21 +277,78 @@ @Override public void commitTransaction() { - //To change body of implemented methods use File | Settings | File Templates. + checkClosed(); + + try { + + Session hibernateSession = hibernateSupport.getHibernateSession(); + + Transaction tx = hibernateSession.getTransaction(); + hibernateSession.flush(); + tx.commit(); + + getFiresSupport().fireOnPostCommit(this); +// TopiaContextImplementor parent = getParentContext(); +// if (parent != null) { +// parent.getFiresSupport().fireOnPostCommit(this); +// } + + hibernateSession.beginTransaction(); + + // it's seem necessary to change session after commit + // NON, NON, NON, il ne faut surtout pas le faire, ca pose plein de + // probleme + // hibernate = getHibernateFactory().openSession(); + // hibernate.setFlushMode(FlushMode.NEVER); + } catch (Exception eee) { + String message = String.format("An error occurred during commit operation: %1$s", eee.getMessage()); + throw new TopiaException(message, eee); + } } @Override public void rollbackTransaction() { - //To change body of implemented methods use File | Settings | File Templates. + checkClosed(); + try { + Session hibernateSession = hibernateSupport.getHibernateSession(); + + Transaction tx = hibernateSession.getTransaction(); + hibernateSession.clear(); + tx.rollback(); + hibernateSession.close(); + + // it's very important to change the session after rollback + // otherwise there are many error during next Entity's modification + hibernateSession = hibernateSupport.getHibernateFactory().openSession(); + hibernateSupport.setHibernateSession(hibernateSession); + hibernateSession.setFlushMode(FlushMode.MANUAL); + + hibernateSession.beginTransaction(); + + getFiresSupport().fireOnPostRollback(this); +// TopiaContextImplementor parent = getParentContext(); +// if (parent != null) { +// parent.getFiresSupport().fireOnPostRollback(this); +// } + + } catch (HibernateException eee) { + String message = String.format("An error occurred during rollback operation: %1$s", eee.getMessage()); + throw new TopiaException(message, eee); + } } @Override - public void closeContext() { - //To change body of implemented methods use File | Settings | File Templates. + public void close() { + checkClosed(); + closed = true; + + // Now close the current Hibernate session + hibernateSupport.getHibernateSession().close(); } @Override public boolean isClosed() { - return false; //To change body of implemented methods use File | Settings | File Templates. + return closed; } + } Modified: trunk/topia-persistence/src/main/java/org/nuiton/topia/TopiaPersistenceContext.java =================================================================== --- trunk/topia-persistence/src/main/java/org/nuiton/topia/TopiaPersistenceContext.java 2013-10-11 15:10:28 UTC (rev 2839) +++ trunk/topia-persistence/src/main/java/org/nuiton/topia/TopiaPersistenceContext.java 2013-10-11 15:13:30 UTC (rev 2840) @@ -64,4 +64,17 @@ */ TopiaIdFactory getTopiaIdFactory(); + /** + * Closes the context. All the children contexts will be closed in the same + * time. + */ + void close(); + + /** + * Tells if the context is closed + * + * @return {@code true} if the context is closed, {@code false} otherwise + */ + boolean isClosed(); + } Modified: trunk/topia-persistence/src/main/java/org/nuiton/topia/TopiaTransaction.java =================================================================== --- trunk/topia-persistence/src/main/java/org/nuiton/topia/TopiaTransaction.java 2013-10-11 15:10:28 UTC (rev 2839) +++ trunk/topia-persistence/src/main/java/org/nuiton/topia/TopiaTransaction.java 2013-10-11 15:13:30 UTC (rev 2840) @@ -45,17 +45,4 @@ */ void rollbackTransaction(); - /** - * Closes the context. All the children contexts will be closed in the same - * time. - */ - void closeContext(); - - /** - * Tells if the context is closed - * - * @return {@code true} if the context is closed, {@code false} otherwise - */ - boolean isClosed(); - } Modified: trunk/topia-persistence/src/main/java/org/nuiton/topia/event/TopiaTransactionEvent.java =================================================================== --- trunk/topia-persistence/src/main/java/org/nuiton/topia/event/TopiaTransactionEvent.java 2013-10-11 15:10:28 UTC (rev 2839) +++ trunk/topia-persistence/src/main/java/org/nuiton/topia/event/TopiaTransactionEvent.java 2013-10-11 15:13:30 UTC (rev 2840) @@ -27,6 +27,7 @@ import org.apache.commons.collections.map.IdentityMap; import org.nuiton.topia.TopiaContext; +import org.nuiton.topia.TopiaTransaction; import org.nuiton.topia.framework.EntityState; import org.nuiton.topia.persistence.TopiaEntity; @@ -47,11 +48,11 @@ private Map<TopiaEntity, EntityState> entities = new IdentityMap(); - public TopiaTransactionEvent(TopiaContext source) { + public TopiaTransactionEvent(TopiaTransaction source) { super(source); } - public TopiaTransactionEvent(TopiaContext source, + public TopiaTransactionEvent(TopiaTransaction source, Map<TopiaEntity, EntityState> entities) { this(source); this.entities.putAll(entities); Modified: trunk/topia-persistence/src/main/java/org/nuiton/topia/framework/AbstractTopiaContext.java =================================================================== --- trunk/topia-persistence/src/main/java/org/nuiton/topia/framework/AbstractTopiaContext.java 2013-10-11 15:10:28 UTC (rev 2839) +++ trunk/topia-persistence/src/main/java/org/nuiton/topia/framework/AbstractTopiaContext.java 2013-10-11 15:13:30 UTC (rev 2840) @@ -890,6 +890,11 @@ } @Override + public void close() { + closeContext(); + } + + @Override public void closeContext() throws TopiaException { // Throw exception if context is already closed checkClosed("Context was already closed"); Modified: trunk/topia-persistence/src/main/java/org/nuiton/topia/framework/TopiaFiresSupport.java =================================================================== --- trunk/topia-persistence/src/main/java/org/nuiton/topia/framework/TopiaFiresSupport.java 2013-10-11 15:10:28 UTC (rev 2839) +++ trunk/topia-persistence/src/main/java/org/nuiton/topia/framework/TopiaFiresSupport.java 2013-10-11 15:13:30 UTC (rev 2840) @@ -55,6 +55,7 @@ import org.nuiton.topia.TopiaJpaSupport; import org.nuiton.topia.TopiaListenableSupport; import org.nuiton.topia.TopiaPersistenceContext; +import org.nuiton.topia.TopiaTransaction; import org.nuiton.topia.TopiaVetoException; import org.nuiton.topia.event.TopiaContextEvent; import org.nuiton.topia.event.TopiaContextListener; @@ -220,7 +221,7 @@ /* Fires sur les transactions */ - public void fireOnBeginTransaction(TopiaContextImplementor context) { + public void fireOnBeginTransaction(TopiaTransaction context) { if (log.isDebugEnabled()) { log.debug("fireOnBeginTransaction"); } @@ -234,7 +235,7 @@ } } - public void fireOnPostCommit(TopiaContextImplementor context) { + public void fireOnPostCommit(TopiaTransaction context) { if (log.isDebugEnabled()) { log.debug("fireOnPostCommit"); } @@ -252,7 +253,7 @@ transactionEntities.clear(); } - public void fireOnPostRollback(TopiaContextImplementor context) { + public void fireOnPostRollback(TopiaTransaction context) { if (log.isDebugEnabled()) { log.debug("fireOnPostRollback"); } Modified: trunk/topia-service-migration/src/main/java/org/nuiton/topia/migration/TopiaMigrationEngine.java =================================================================== --- trunk/topia-service-migration/src/main/java/org/nuiton/topia/migration/TopiaMigrationEngine.java 2013-10-11 15:10:28 UTC (rev 2839) +++ trunk/topia-service-migration/src/main/java/org/nuiton/topia/migration/TopiaMigrationEngine.java 2013-10-11 15:13:30 UTC (rev 2840) @@ -38,6 +38,7 @@ import org.nuiton.topia.event.TopiaContextListener; import org.nuiton.topia.event.TopiaTransactionEvent; import org.nuiton.topia.event.TopiaTransactionVetoable; +import org.nuiton.topia.framework.AbstractTopiaContext; import org.nuiton.topia.framework.TopiaContextImplementor; import org.nuiton.topia.framework.TopiaUtil; import org.nuiton.topia.migration.mappings.TMSVersion; @@ -197,7 +198,7 @@ public boolean preInit(TopiaContext context) { rootContext = context; - Properties config = context.getConfig(); + Properties config = ((AbstractTopiaContext)context).getConfig(); String callbackStr = getSafeParameter(config, MIGRATION_CALLBACK); if (log.isDebugEnabled()) { @@ -657,7 +658,7 @@ * @since 2.5.3 */ protected Configuration createHibernateConfiguration(Configuration configuration) { - Properties config = rootContext.getConfig(); + Properties config = ((AbstractTopiaContext)rootContext).getConfig(); Properties prop = new Properties(); prop.putAll(configuration.getProperties());