StaleStateException using many-to-many together with one-to-many
----------------------------------------------------------------
Key: HHH-3152
URL:
http://opensource.atlassian.com/projects/hibernate/browse/HHH-3152
Project: Hibernate3
Issue Type: Bug
Components: core
Affects Versions: 3.2.6
Environment: Hibernate EntityManager 3.3.1 GA, Hibernate Annotations 3.3.0 GA,
Hibernate Core 3.2.6 GA.
DB2 9.5 (production), Derby 10.3.2.1 (reproducible test case)
Reporter: Donatas Ciuksys
Attachments: db_schema.gif, ManyToMany.zip
I have many-to-many association between tables A and B (via join table A_B, see attached
db_schema.gif). Join table has additional data columns, so I represent it as entity AB and
have two one-to-many associations (A <-> AB and B <-> AB, with
cascade=Cascade.REMOVE). Also I have many-to-many association between A and B (joinColumns
are marked with insertable=false, updatable=false, though the marking/unmarking
doesn't change the behaviour).
Table A is modeled as abstract entity A that is inherited by two concrete entities ATrue
and AFalse. Table A has column BOOL_PROP (boolean property) of type INTEGER. ATrue spans
objects with BOOL_PROP being true (1), AFalse - being false (0), column BOOL_PROP is used
as Discriminator column.
The problem: having in database several ATrue and AFalse entities, it is impossible to
delete ATrue entity - StaleStateException is being thrown:
Code fragment (p.getAllTrueA() return list of ATrue entities):
em.getTransaction().begin();
em.remove(p.getAllTrueA().get(0));
em.getTransaction().commit();
Log and exception stack trace:
Hibernate: delete from A_B where A=?
2008-03-03 18:02:10,313 [main] DEBUG org.hibernate.type.IntegerType - binding '4'
to parameter: 1
Hibernate: delete from ADMIN.A_B where ID=?
2008-03-03 18:02:10,403 [main] DEBUG org.hibernate.type.IntegerType - binding '4'
to parameter: 1
2008-03-03 18:02:10,473 [main] ERROR org.hibernate.event.def.AbstractFlushingEventListener
- Could not synchronize database state with session
org.hibernate.StaleStateException: Batch update returned unexpected row count from update
[0]; actual row count: 0; expected: 1
at org.hibernate.jdbc.Expectations$BasicExpectation.checkBatched(Expectations.java:61)
...
at org.hibernate.ejb.TransactionImpl.commit(TransactionImpl.java:54)
at manytomany.Main.run(Main.java:30)
at manytomany.Main.main(Main.java:15)
Exception in thread "main" javax.persistence.RollbackException: Error while
commiting the transaction
at org.hibernate.ejb.TransactionImpl.commit(TransactionImpl.java:71)
at manytomany.Main.run(Main.java:30)
at manytomany.Main.main(Main.java:15)
Caused by: javax.persistence.OptimisticLockException: org.hibernate.StaleStateException:
Batch update returned unexpected row count from update [0]; actual row count: 0; expected:
1
at
org.hibernate.ejb.AbstractEntityManagerImpl.wrapStaleStateException(AbstractEntityManagerImpl.java:654)
at org.hibernate.ejb.TransactionImpl.commit(TransactionImpl.java:59)
... 2 more
Caused by: org.hibernate.StaleStateException: Batch update returned unexpected row count
from update [0]; actual row count: 0; expected: 1
at org.hibernate.jdbc.Expectations$BasicExpectation.checkBatched(Expectations.java:61)
...
The problem is that after:
Hibernate: delete from A_B where A=?
following statement is being executed:
Hibernate: delete from ADMIN.A_B where ID=?
The first statement deletes child A_B rows belonging to parent A. The second tries to
delete what is already deleted.
Why I think it is related to many-to-many association: if I comment many-to-many
association fields and getters/setters, problem is gone.
Attached is Eclipse project (standard java application), Derby DDL scripts. Following
steps are needed to reproduce the problem:
1. Adjust the classpath (specify correct path to Hibernate EntityManager and its
dependencies, Derby 10.3 derbyclient.jar)
2. Adjust database URL in /src/META-INF/persistence.xml (I'm using absolute path to
DB, that is located at the projects root)
3. Start Derby network server (or adjust database URL to use embedded driver)
4. Start the application - it tries to delete ATrue entity and fails.
You can recreated the database if you wish - projects root folder contains DB_DDL.sql
scripts. The program checks, whether the DB is empty, and if so, first fills it up with
test data, then exits. Restart it again - it will load some ATrue entities and will try to
delete one.
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators:
http://opensource.atlassian.com/projects/hibernate/secure/Administrators....
-
For more information on JIRA, see:
http://www.atlassian.com/software/jira