编辑:我搬了em1.getTransaction()。提交是正确的之后em1.flush();
会话em1 = Manager.sessionFactory.openSession(); Session em2 = Manager.sessionFactory.openSession(); em1.getTransaction()。begin(); em2.getTransaction()。begin(); UserAccount c1 =(UserAccount)em1.get(UserAccount.class,root); UserAccount c2 =(UserAccount)em2.get(UserAccount.class,root); c1.setBalance(c1.getBalance()-1); em1.flush(); System.out.println(balance1 is+ c2.getBalance()); c2.setBalance(c2.getBalance()-1); em2.flush(); //失败 em1.getTransaction()。commit(); em2.getTransaction()。commit(); System.out.println(balance2 is+ c2.getBalance());我在 em2.flush()。为什么?
2009-12-23 21:48:37,648 WARN JDBCExceptionReporter:100 - SQL错误:1205,SQLState:41000 2009-12-23 21:48:37,649错误JDBCExceptionReporter:101 - 锁超时超时;尝试重新启动事务错误AbstractFlushingEventListener:324 - 无法使数据库状态与会话同步org.hibernate.exception.GenericJDBCException:无法执行JDBC批量更新在org.hibernate.exception.SQLStateConverter.handledNonSpecificException(SQLStateConverter.java:126)在org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:114)在org.hibernate.exception。 JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66) at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:275) at org.hibernate.persister.entity.AbstractEntityPersister.processGeneratedProperties(AbstractEntityPersister。 at org.hibernate.persister.entity.AbstractEntityPersister.processUpdateGeneratedProperties(AbstractEntityPersister.java:3691) at org.hibernate.action.EntityUpdateAction.execute(EntityUpdateAction.java:147)$ b $ org.hibernate.engine。 ActionQueue.execute(ActionQueue.java:279)在org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:263)在org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java: at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:321) at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:50) at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1028) at com.ch.whoisserver.test.StressTest.main(StressTest.java:54)导致:java .sql.BatchUpdateException:超出锁定等待超时;尝试重新启动事务在com.mysql.jdbc.PreparedStatement.executeBatchSerially(PreparedStatement.java:1213)在com.mysql.jdbc.PreparedStatement.executeBatch(PreparedStatement.java:912) at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:70) at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:268) ... 10 more解决方案
好吧,您正试图陷入僵局,而您成功: - )
$ b
真实生活和第二个实体管理器加上适当的更新/交易在不同的线程。这样您就可以:
请注意,在这一点(上面#4),您将覆盖Transaction1所做的更改。 Hibernate可以使用乐观锁定以及悲观锁定,以防止这种情况发生。
更新(基于评论):
如果实体版本化,Transaction2(上面的#4)将失败。但是,您发布的代码没有达到该点,因为Transaction2无法获得上述的锁定。如果您想专门测试乐观版本控制是否正常工作,您可以执行以下操作:
I am using Hibernate, trying to simulate 2 concurrent update to the same row in database.
Edit: I moved em1.getTransaction()mit to be right after em1.flush(); I am not getting any StaleObjectException, the two transactions committed successfully.
Session em1=Manager.sessionFactory.openSession(); Session em2=Manager.sessionFactory.openSession(); em1.getTransaction().begin(); em2.getTransaction().begin(); UserAccount c1 = (UserAccount)em1.get( UserAccount.class, "root" ); UserAccount c2 = (UserAccount)em2.get( UserAccount.class, "root" ); c1.setBalance( c1.getBalance() -1 ); em1.flush(); System.out.println("balance1 is "+c2.getBalance()); c2.setBalance( c2.getBalance() -1 ); em2.flush(); // fail em1.getTransaction()mit(); em2.getTransaction()mit(); System.out.println("balance2 is "+c2.getBalance());I getting the following exception on em2.flush(). Why?
2009-12-23 21:48:37,648 WARN JDBCExceptionReporter:100 - SQL Error: 1205, SQLState: 41000 2009-12-23 21:48:37,649 ERROR JDBCExceptionReporter:101 - Lock wait timeout exceeded; try restarting transaction 2009-12-23 21:48:37,650 ERROR AbstractFlushingEventListener:324 - Could not synchronize database state with session org.hibernate.exception.GenericJDBCException: Could not execute JDBC batch update at org.hibernate.exception.SQLStateConverter.handledNonSpecificException(SQLStateConverter.java:126) at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:114) at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66) at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:275) at org.hibernate.persister.entity.AbstractEntityPersister.processGeneratedProperties(AbstractEntityPersister.java:3702) at org.hibernate.persister.entity.AbstractEntityPersister.processUpdateGeneratedProperties(AbstractEntityPersister.java:3691) at org.hibernate.action.EntityUpdateAction.execute(EntityUpdateAction.java:147) at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:279) at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:263) at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:168) at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:321) at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:50) at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1028) at com.ch.whoisserver.test.StressTest.main(StressTest.java:54) Caused by: java.sql.BatchUpdateException: Lock wait timeout exceeded; try restarting transaction at com.mysql.jdbc.PreparedStatement.executeBatchSerially(PreparedStatement.java:1213) at com.mysql.jdbc.PreparedStatement.executeBatch(PreparedStatement.java:912) at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:70) at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:268) ... 10 more解决方案
Well, you're trying to get into a deadlock and you're succeeding :-)
Real life simulation would have 1st and 2nd entity manager plus appropriate updates / transactions in separate threads. That way you'd have:
Note that at that point (#4 above) you'd be overwriting changes made by Transaction1. Hibernate can use optimistic locking as well as pessimistic locking to prevent that from happening.
Update (based on comment):
If the entity is versioned, Transaction2 (#4 above) will fail. However, your code as posted does not get to that point because Transaction2 can't obtain the lock as explained above. If you want to specifically test that optimistic version control is working you can do the following:
更多推荐
休眠超时锁定等待超时;
发布评论