Używam Hibernate, próbując symulować 2 równoczesne aktualizacje do tego samego wiersza w bazie danych.przekroczony limit czasu oczekiwania na hibernację blokady;
Edytuj: Wprowadziłem em1.getTransaction(). Commit, aby być zaraz po em1.flush(); Nie otrzymuję żadnego StaleObjectException, obie transakcje zostały pomyślnie zatwierdzone.
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().commit();
em2.getTransaction().commit();
System.out.println("balance2 is "+c2.getBalance());
Otrzymuję następujący wyjątek na em2.flush()
. Czemu?
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
Właściwie próbuję napisać przypadek testowy, aby zobaczyć, czy działa optymistyczne blokowanie, przedmiot UserAccount, o którym mowa, używa wersji, zobacz szczegółowe pytanie http://stackoverflow.com/questions/1938671/concurrency- w trybie hibernacji, w tym przypadku z dwoma wątkami transakcja2 uzyskałby wyjątek staledObjectException w celu wykrycia zmiany w podstawowych danych? – user217631
@unknown Tak, to by było. – KLE
Zaktualizowałem swoją odpowiedź powyżej - używanie dwóch wątków nie jest dobrym sposobem na przetestowanie ** specjalnie ** optymistycznego blokowania (z powodu nieprzewidywalności) – ChssPly76