Posts Tagged ‘Hibernate’
Transaction Management with Spring in AOP
Case
You have a couple of Hibernate DAOs, in which a huge amount of code is duplicated: begin transactions, try/catch, close transactions, etc.
You would like to factorize your code.
Fix
- Define a
SessionFactory, let’s sayhibernateSessionFactory, with your own settings.[xml]<bean id="hibernateSessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">(…)</bean>[/xml] - Define a
TransactionManager:[xml]<bean id="hibernateTransactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory">
<ref local="hibernateSessionFactory" />
</property>
</bean>[/xml] - Define transactions advices:
[xml]<tx:advice id="hibTxManager" transaction-manager="hibernateTransactionManager">
<tx:attributes>
<tx:method name="*" propagation="NEVER" read-only="true" isolation="READ_COMMITTED" rollback-for="find*" no-rollback-for="dontFind*"/>
</tx:attributes>
</tx:advice>[/xml] name="*"–> the aspect will apply to all methods. You may filter on patterns such as find*, get*, save*, etc.propagation="NEVER"–> hints the propagation level. Available options areREQUIRED, SUPPORTS, MANDATORY,REQUIRES_NEW, NOT_SUPPORTED, NEVER, NESTED.isolation="READ_COMMITTED"–>rollback-for="find*"–> rollback all transactions following the given patternno-rollback-for="dontFind*"–> exceptions for rollbacks- Define the AOP configuration:
[xml]<aop:config>
<aop:pointcut id="hibOperation"
expression="execution(* com.lalou.jonathan.dao.hibernate.Hibernate*.*(..))" />
<aop:advisor pointcut-ref="hibOperation" advice-ref="hibTxManager" />
</aop:config>[/xml]
Many thanks to Jean-Pierre ISOARD for his help on this subject.
“Select for update” in Hibernate
Case:
You have to use an equivalent to “select for update” in Hibernate, for instance when you migrate en EJB entity to Hibernate.
Fix:
In your query, use the option LockMode.UPGRADE. For instance, you will have:
[java]sessionFactory.getCurrentSession().load(MyMappedClass.class, myPk, LockMode.UPGRADE);[/java]
Short Tutorial: Migration from EJB Entity to Hibernate
Case
- let’s consider an EJB Bean AnimalBean, linked to a table JL_Animal
- let’s have a human understandable name for the Pojo, let’s say: Animal
- let an EJB entity have following finders:
[java]
* @ejb.finder
* signature = "Collection findByBirthDate(java.lang.Integer birthDate)"
* query = "SELECT OBJECT(o) FROM AnimalBean AS o WHERE o.birthDate = ?1"
*
* @ejb.finder
* signature = "Collection findByCountryAndBirthDate(java.lang.String from,java.lang.Integer birthDate)"
* query = "SELECT OBJECT(o) FROM AnimalBean AS o WHERE o.country = ?1 AND o.birthDate = ?2"[/java]
Read the rest of this entry »
DBUnit and Hibernate: Beware of Collisions!
Here is an interesting case I have encountered this morning.
Context
I must test a Hibernate implementation of a DAO, using DBUnit and its XML dataset files as a minimal database. A CRUD unit test fails, I get this trace:
| WARN util.JDBCExceptionReporter – SQL Error: 0, SQLState: null ERROR util.JDBCExceptionReporter – failed batch ERROR def.AbstractFlushingEventListener – Could not synchronize database state with session org.hibernate.exception.GenericJDBCException: Could not execute JDBC batch update |
Explanation
In my dataset, I had set some primary keys at 0, 1, …, 10. Owing to my Hibernate mapping, the primary keys are generated thanks to a sequence.
On another hand, with the CRUD test, the primary keys 0, 1, …, 10 are also assigned to newly created objects.
Here is the issue: there are collisions between the XML dataset file objects and the objects created with Hibernate, because obviously two objects never share the same primary key!
“Position” is a reserved word in SQL!
Very interesting case. At firt, I spotted these errors:
SQL Error: -22, SQLState: S0002
and:
java.sql.SQLException: Table not found in statement
But here is the complete stacktrace:
"2009-10-13 12:29:17,934 ERROR hbm2ddl.SchemaExport - Unsuccessful: create table MY_ORACLE_TABLE (myOracleTableId integer not null, optimisticTimestamp timestamp not null, position double, primary key (myOracleTableId)) 2009-10-13 12:29:17,934 ERROR hbm2ddl.SchemaExport - Unexpected token: POSITION in statement [create table MY_ORACLE_TABLE (myOracleTableId integer not null, optimisticTimestamp timestamp not null, position] (...) 2009-10-13 12:29:17,949 ERROR hbm2ddl.SchemaExport - Table not found: MY_ORACLE_TABLE in statement [alter table MY_ORACLE_TABLE] 2009-10-13 12:29:17,980 DEBUG util.HibernatePersistenceTestCase - ++++++++++++++ Using Pattern HibernateMyOracleTableDAOUnitTest-testFindmyOracleTableByPK_OK.xml 2009-10-13 12:29:17,996 DEBUG util.HibernatePersistenceTestCase - ++++++++++++++ Using Pattern HibernateMyOracleTableDAOUnitTest.xml 2009-10-13 12:29:17,996 DEBUG util.HibernatePersistenceTestCase - --------------- Using dataset : HibernateMyOracleTableDAOUnitTest.xml 2009-10-13 12:29:18,355 WARN util.JDBCExceptionReporter - SQL Error: -22, SQLState: S0002 2009-10-13 12:29:18,355 ERROR util.JDBCExceptionReporter - Table not found in statement [select (...) where myOracleTable0_.myOracleTableId=?] 2009-10-13 12:29:18,371 DEBUG util.HibernatePersistenceTestCase - ++++++++++++++ Using Pattern HibernateMyOracleTableDAOUnitTest-testFindmyOracleTableByPK_OK.xml 2009-10-13 12:29:18,371 DEBUG util.HibernatePersistenceTestCase - ++++++++++++++ Using Pattern HibernateMyOracleTableDAOUnitTest.xml 2009-10-13 12:29:18,387 DEBUG util.HibernatePersistenceTestCase - --------------- Using dataset : HibernateMyOracleTableDAOUnitTest.xml org.hibernate.exception.SQLGrammarException: could not load an entity: [com.(...)myOracleTable#147] at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:67) at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43) at org.hibernate.loader.Loader.loadEntity(Loader.java:1799) at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:47) at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:41) at org.hibernate.persister.entity.AbstractEntityPersister.load(AbstractEntityPersister.java:2730) at org.hibernate.event.def.DefaultLoadEventListener.loadFromDatasource(DefaultLoadEventListener.java:365) at org.hibernate.event.def.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:346) at org.hibernate.event.def.DefaultLoadEventListener.load(DefaultLoadEventListener.java:123) at org.hibernate.event.def.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:161) at org.hibernate.event.def.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:87) at org.hibernate.impl.SessionImpl.fireLoad(SessionImpl.java:862) at org.hibernate.impl.SessionImpl.load(SessionImpl.java:781) at org.hibernate.impl.SessionImpl.load(SessionImpl.java:774) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at org.hibernate.context.ThreadLocalSessionContext$TransactionProtectionWrapper.invoke(ThreadLocalSessionContext.java:301) at $Proxy0.load(Unknown Source) (...)HibernateMyOracleTableDAOUnitTest.java:37) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:40) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at com.intellij.rt.execution.application.AppMain.main(AppMain.java:90) Caused by: java.sql.SQLException: Table not found in statement [select (...) where myOracleTable0.myOracleTableId=?] at org.hsqldb.jdbc.Util.throwError(Unknown Source) at org.hsqldb.jdbc.jdbcPreparedStatement.(Unknown Source) at org.hsqldb.jdbc.jdbcConnection.prepareStatement(Unknown Source) at org.hibernate.jdbc.AbstractBatcher.getPreparedStatement(AbstractBatcher.java:442) at org.hibernate.jdbc.AbstractBatcher.getPreparedStatement(AbstractBatcher.java:368) at org.hibernate.jdbc.AbstractBatcher.prepareQueryStatement(AbstractBatcher.java:105) at org.hibernate.loader.Loader.prepareQueryStatement(Loader.java:1561) at org.hibernate.loader.Loader.doQuery(Loader.java:661) at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:224) at org.hibernate.loader.Loader.loadEntity(Loader.java:1785) ... 42 more" |
I have helped you with red bold words… Can you see the issue?
Yes, indeed position is a reserved keyword in SQL! To fix this issue, you have no choice but to rename your column.
Utiliser des enum de Java5 avec Hibernate
org.hibernate.hql.antlr.HqlBaseParser.recover(Lantlr/RecognitionException;Lantlr/collections/impl/BitSet;)V
Error:
java.lang.reflect.UndeclaredThrowableException at $Proxy0.createQuery(Unknown Source) at somewhere in some Hibernate DAO... at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:40) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at com.intellij.rt.execution.application.AppMain.main(AppMain.java:90) Caused by: java.lang.reflect.InvocationTargetException at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at org.hibernate.context.ThreadLocalSessionContext$TransactionProtectionWrapper.invoke(ThreadLocalSessionContext.java:301) ... 26 more Caused by: java.lang.NoSuchMethodError: org.hibernate.hql.antlr.HqlBaseParser.recover(Lantlr/RecognitionException;Lantlr/collections/impl/BitSet;)V
Fix: Upgrade AntLR from version 2.7.2 to 2.7.6
ids for this class must be manually assigned before calling save()
Error:
javax.ejb.EJBException: EJB Exception: : org.hibernate.id.IdentifierGenerationException: ids for this class must be manually assigned before calling save():
Fix: You must assign the primary-key (which is probably a composite-id) before saving the object.
java.lang.NullPointerException at org.dbunit.dataset.DefaultTableIterator.next
Still another dumb error:
java.lang.NullPointerException at org.dbunit.dataset.DefaultTableIterator.next(DefaultTableIterator.java:59) at org.dbunit.dataset.AbstractDataSet.getTable(AbstractDataSet.java:77) at org.dbunit.dataset.AbstractDataSet.getTableMetaData(AbstractDataSet.java:70) at org.dbunit.dataset.filter.SequenceTableFilter.getTableNames(SequenceTableFilter.java:94) at org.dbunit.dataset.filter.SequenceTableFilter.iterator(SequenceTableFilter.java:110) at org.dbunit.dataset.FilteredDataSet.createIterator(FilteredDataSet.java:74) at org.dbunit.dataset.AbstractDataSet.iterator(AbstractDataSet.java:112) at org.dbunit.operation.DeleteAllOperation.execute(DeleteAllOperation.java:81)
I’m laughing because I had only to check the DBUnit XML file did start with <dataset> tag… :-S