|
View:
New views
5 Messages
—
Rating Filter:
Alert me
|
|
|
JPA: Cascade.REMOVE not working for unidirectional OneToMany-RelationshipHello,
I have justed switched from Toplink Essentials to EclipseLink. I am using Glassfish v2, JPA and MySQL 5. So far, almost everything seems to work fine. But Cascade.REMOVE does not work for unidirectional OneToMany-Relationships that are associated via a JoinTable. Example: -------- [User Entity] 1 --------> N [Invitation Entity] Now, when passing a user entity to the remove() method of the EntityManager I get the following exception: [#|2008-07-21T19:46:56.939+0200|WARNING|sun-appserver9.1|org.eclipse.persistence.session.file:/C:/Programme/Sun/SDK/domains/domain1/applications/j2ee-apps/war/war-ejb_jar/-war-ejbPU|_ThreadID=18;_ThreadName=httpSSLWorkerThread-8080-1;_RequestID=8e614318-51e6-483b-9c21-14ba2326e340;| Local Exception Stack: Exception [EclipseLink-4002] (Eclipse Persistence Services - 1.0 (Build 1.0 - 20080707)): org.eclipse.persistence.exceptions.DatabaseException Internal Exception: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Cannot delete or update a parent row: a foreign key constraint fails (`war_db/lkp_users_invitations`, CONSTRAINT `FK_lkp_users_invitations__invitation_id` FOREIGN KEY (`_invitation_id`) REFERENCES `invitations` (`_id`)) Error Code: 1451 Call: DELETE FROM invitations WHERE (_id = ?) bind => [1000] Query: DeleteObjectQuery(com.war.bus.data.entity.Invitation@43f) at org.eclipse.persistence.exceptions.DatabaseException.sqlException(DatabaseException.java:313) at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeDirectNoSelect(DatabaseAccessor.java:757) at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeNoSelect(DatabaseAccessor.java:823) at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.basicExecuteCall(DatabaseAccessor.java:557) at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeCall(DatabaseAccessor.java:500) at org.eclipse.persistence.internal.sessions.AbstractSession.executeCall(AbstractSession.java:855) at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:204) at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:190) at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.deleteObject(DatasourceCallQueryMechanism.java:181) at org.eclipse.persistence.internal.queries.StatementQueryMechanism.deleteObject(StatementQueryMechanism.java:102) at org.eclipse.persistence.queries.DeleteObjectQuery.executeDatabaseQuery(DeleteObjectQuery.java:168) at org.eclipse.persistence.queries.DatabaseQuery.execute(DatabaseQuery.java:666) at org.eclipse.persistence.queries.DatabaseQuery.executeInUnitOfWork(DatabaseQuery.java:585) at org.eclipse.persistence.queries.ObjectLevelModifyQuery.executeInUnitOfWorkObjectLevelModifyQuery(ObjectLevelModifyQuery.java:114) at org.eclipse.persistence.queries.DeleteObjectQuery.executeInUnitOfWorkObjectLevelModifyQuery(DeleteObjectQuery.java:113) at org.eclipse.persistence.queries.ObjectLevelModifyQuery.executeInUnitOfWork(ObjectLevelModifyQuery.java:86) at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.internalExecuteQuery(UnitOfWorkImpl.java:2588) at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1178) at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1162) at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1108) at org.eclipse.persistence.internal.sessions.CommitManager.deleteAllObjects(CommitManager.java:326) at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitToDatabase(UnitOfWorkImpl.java:1245) at org.eclipse.persistence.internal.jpa.RepeatableWriteUnitOfWork.commitToDatabase(RepeatableWriteUnitOfWork.java:482) at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitToDatabaseWithChangeSet(UnitOfWorkImpl.java:1331) at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.issueSQLbeforeCompletion(UnitOfWorkImpl.java:2849) at org.eclipse.persistence.internal.jpa.RepeatableWriteUnitOfWork.issueSQLbeforeCompletion(RepeatableWriteUnitOfWork.java:227) at org.eclipse.persistence.transaction.AbstractSynchronizationListener.beforeCompletion(AbstractSynchronizationListener.java:157) at org.eclipse.persistence.transaction.JTASynchronizationListener.beforeCompletion(JTASynchronizationListener.java:68) at com.sun.enterprise.distributedtx.J2EETransaction.commit(J2EETransaction.java:419) at com.sun.enterprise.distributedtx.J2EETransactionManagerOpt.commit(J2EETransactionManagerOpt.java:371) //.... rest of stacktrace For me, it seems that EclipseLink does not remove the rows from the join table when deleting the entities that are affected by Cascade.REMOVE. I have several unidirectional OneToMany relationships marked with Cascade.REMOVE in my app. They all share this problem. I also want to make clear that my app worked perfectly when I was using Toplink Essentials. I have not made any changes to the source code of my app except ... The only things I changed were: - copied "eclipselink.jar" to domain1\lib - altered "persistence.xml" My persistence.xml: <?xml version="1.0" encoding="UTF-8"?> <persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence persistence_1_0.xsd"> <persistence-unit name="war-ejbPU" transaction-type="JTA"> <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider> <jta-data-source>jdbc/WarConnectionPool</jta-data-source> <properties> <property name="eclipselink.target-server" value="SunAS9"/> <property name="eclipselink.ddl-generation" value="create-tables"/> <property name="eclipselink.ddl-generation.output-mode" value="database"/> <property name="eclipselink.logging.level" value="finest"/> </properties> </persistence-unit> </persistence> Maybe someone can give me a hint why I am running into this problem (or is it a bug?). |
|
|
Re: JPA: Cascade.REMOVE not working for unidirectional OneToMany-Relationship |
|
|
Re: JPA: Cascade.REMOVE not working for unidirectional OneToMany-RelationshipI updated the bug with the details, and workarounds.
The best workaround is most likely to make the relationship @PrivateOwned until the bug is fixed.
James Sutherland EclipseLink, TopLink Wiki: EclipseLink, TopLink Forums: TopLink, EclipseLink Book: Java Persistence |
|
|
Re: JPA: Cascade.REMOVE not working for unidirectional OneToMany-RelationshipHi,
A one-to-one, bi-direction mapping where the owner side using a simple derived identity fails to delete by query depending on the order of execution. > The best workaround is most likely to make the relationship @PrivateOwned until the bug is fixed. It works if the owner side is deleted *before* the owned side. Here are the two ends of a one-to-one bi-directional relation, Book and its Inventory. Inventory owns the mapping and uses derived identity from the corresponding Book. ------------ Book.java ----------------------- @Entity public class Book implements Serializable { @Id private String ISBN; @OneToOne(mappedBy="book", fetch=FetchType.LAZY, cascade=CascadeType.ALL) private Inventory inventory; ----------- Inventory.java -------------------- @Entity public class Inventory implements Serializable { @Id @OneToOne(fetch=FetchType.LAZY) private Book book; Here is the working application code to clean the tables. If the owner side table is deleted first, it works. If the order of two delete-by-query is swapped, then the runtime fails with the stacktrace mentioned below. em.getTransaction().begin(); em.createQuery("delete from Inventory i").executeUpdate(); em.createQuery("delete from Book b").executeUpdate(); em.getTransaction().commit(); [java] Caused by: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.0.0.v20091127-r5931): org.eclipse.persistence.exceptions.DatabaseException [java] Internal Exception: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Cannot delete or update a parent row: a foreign key constraint fails (`openbook/inventory`, CONSTRAINT `FK_INVENTORY_BOOK_ISBN` FOREIGN KEY (`BOOK_ISBN`) REFERENCES `book` (`ISBN`)) [java] Error Code: 1451 [java] Call: DELETE FROM BOOK [java] Query: DeleteAllQuery(referenceClass=Book sql="DELETE FROM BOOK") [java] at org.eclipse.persistence.exceptions.DatabaseException.sqlException(DatabaseException.java:324) [java] at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeDirectNoSelect(DatabaseAccessor.java:800) [java] at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeNoSelect(DatabaseAccessor.java:866) [java] at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.basicExecuteCall(DatabaseAccessor.java:586) [java] at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeCall(DatabaseAccessor.java:529) [java] at org.eclipse.persistence.internal.sessions.AbstractSession.executeCall(AbstractSession.java:914) [java] at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:205) [java] at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.deleteAll(DatasourceCallQueryMechanism.java:94) [java] at org.eclipse.persistence.queries.DeleteAllQuery.executeDatabaseQuery(DeleteAllQuery.java:174) [java] at org.eclipse.persistence.queries.DatabaseQuery.execute(DatabaseQuery.java:675) [java] at org.eclipse.persistence.queries.DatabaseQuery.executeInUnitOfWork(DatabaseQuery.java:589) [java] at org.eclipse.persistence.queries.ModifyAllQuery.executeInUnitOfWork(ModifyAllQuery.java:145) [java] at org.eclipse.persistence.queries.DeleteAllQuery.executeInUnitOfWork(DeleteAllQuery.java:100) [java] at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.internalExecuteQuery(UnitOfWorkImpl.java:2863) [java] at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1225) [java] at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1207) [java] at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1181) [java] at org.eclipse.persistence.internal.jpa.EJBQueryImpl.executeUpdate(EJBQueryImpl.java:508) [java] at openbook.server.DataLoader.clear(Unknown Source)
|
|
|
Re: JPA: Cascade.REMOVE not working for unidirectional OneToMany-RelationshipYou are executing a delete all JPQL query. This is basically similar to executing your own SQL, you are responsible for executing the query correctly to maintain your constraints.
This is not the normal way to delete objects in JPA. In JPA you normally read the object, then call remove() on it. When an object is removed, EclipseLink is responsible to delete it correctly based on the database constraints it knows about.
|
| Free embeddable forum powered by Nabble | Forum Help |