hibernate transaction not rolling back correctly
Transactions don't "cascade". At the JDBC level, a transaction consists of:
- Turning off autocommit
- Executing some statements
- Calling java.sql.Connection.commit() or java.sql.Connection.rollback().
If you're saying that some things are being committed and some are rolled back, then there's something wrong in your transaction management. Either autocommit is on or you actually have multiple calls to commit() happening.
PPP
Updated on June 09, 2022Comments
-
PPP almost 2 years
I have 2 tables, say Item and Property and a hibernate object mapped to both. The mapping for table Item to Property looks like
<set name="propertySet" cascade="all-delete-orphan"> <key column="item_id" not-null="true"/> <one-to-many class="Property"/> </set>
An item can have multiple properties. Everything like select, insert works properly. but when there is an error, the inserts to the property table do not rollback.
What happens is that if i am editing an item with N properties and enter an invalid value in a field, the next time I retrieve the item, it has 2*N properties.
Edit ---
What my class looks like is
@Autowired SessionFactory sessionFactory @Transactional public void updateItem(Item i){ ... // The only 2 statements dealing with hibernate or session in this function ItemModel im = sessionFactory.getCurrentSession().get(...); sessionFactory.getCurrentSession().update(updatedItem); ... }
I am using annotated transactions (@Transactional) with the spring framework and the lowest exception getting thrown is
Caused by: org.springframework.transaction.TransactionSystemException: Could not roll back Hibernate transaction; nested exception is org.hibernate.Tra nsactionException: Transaction not successfully started at org.springframework.orm.hibernate3.HibernateTransactionManager.doRollback(HibernateTransactionManager.java:679) at org.springframework.transaction.support.AbstractPlatformTransactionManager.processRollback(AbstractPlatformTransactionManager.java:845) at org.springframework.transaction.support.AbstractPlatformTransactionManager.rollback(AbstractPlatformTransactionManager.java:822) at org.springframework.transaction.interceptor.TransactionAspectSupport.completeTransactionAfterThrowing(TransactionAspectSupport.java:412) at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:111) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:625) Caused by: org.hibernate.TransactionException: Transaction not successfully started at org.hibernate.transaction.JDBCTransaction.rollback(JDBCTransaction.java:183) at org.springframework.orm.hibernate3.HibernateTransactionManager.doRollback(HibernateTransactionManager.java:676) at org.springframework.transaction.support.AbstractPlatformTransactionManager.processRollback(AbstractPlatformTransactionManager.java:845) at org.springframework.transaction.support.AbstractPlatformTransactionManager.rollback(AbstractPlatformTransactionManager.java:822) at org.springframework.transaction.interceptor.TransactionAspectSupport.completeTransactionAfterThrowing(TransactionAspectSupport.java:412) at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:111) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:625) ... ... at org.apache.catalina.valves.SSLValve.invoke(SSLValve.java:113) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:286) at org.apache.coyote.http11.Http11NioProcessor.process(Http11NioProcessor.java:894) at org.apache.coyote.http11.Http11NioProtocol$Http11ConnectionHandler.process(Http11NioProtocol.java:719) at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:2101) at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908) at java.lang.Thread.run(Thread.java:662)
-
PPP over 12 yearsupdated the question to make it more clear and with some exceptions I got with more debugging. I am no longer making any calls to rollback or commit since i am assuming that the @Transactional annotation already does that for me.
-
Ryan Stewart over 12 yearsProperly configured, @Transactional establishes declarative transaction boundaries where Spring will begin, commit, and roll back exceptions for you as appropriate. If you're doing anything like opening sessions or beginning, committing, or rolling back transactions yourself, that will interfere. The code you've posted has nothing apparently wrong, but it's only a tiny snippet and doesn't include any of your transaction configuration, either. The exception indicates something abnormal is happening because Spring will never try to commit/roll back a transaction that wasn't started.
-
PPP over 12 yearsWhat transaction configuration do I need? spring is using the c3p0 connection pool in the backend for handling database connections. There is no statement that opens or starts any transaction or session on its own. there are only 2 statements in the function dealing with hibernate or session. I tried my own session and transaction stuff thinking that might be the problem but that didnt work either
-
PPP over 12 yearsi already have something simliar in the config. <tx:annotation-driven transaction-manager="txManager" mode='proxy' proxy-target-class='true' /> and the bean config is the same except that the id='txManager'.
-
Ryan Stewart over 12 yearsAre you actually seeing partial commits/rollbacks, or are you just seeing things getting committed when an exception is thrown? Do you realize that checked exceptions don't trigger a rollback by default?
-
PPP over 12 yearsI added a <tx:advice> section and added the attribute <tx:method name="*" rollback-for="Throwable" /> in it. What else do i need to do to ensure the transaction rollbacks?
-
PPP over 12 yearsIn my sql server logs, what i see is 'set autocommit=1' 'rollback' 'rollback' 'update table1 ...' 'insert into table2..' 'set autocommit=0' 'set autocommit=1' 'rollback' 'commit'
-
Ryan Stewart over 12 yearsThat looks to me like autocommit is on. See #1 in my list. If autocommit is on, transactions are useless.
-
PPP over 12 yearshow do I turn it off then? is it something I have to set in the mysql instance or somewhere in the spring config?
-
Ryan Stewart over 12 yearsIt's been a long time since I used mysql. When I did, the default engine didn't support transactions at all, so you had to first be sure to use the InnoDB engine instead. Otherwise, you might find autocommit settings in your JDBC driver, your DataSource implementation, Hibernate, and/or possibly exposed through Spring somewhere. You'd just have to look around. In general, autocommit should already be off, so there's probably something fishy somewhere. I'd check the database engine first.