12 Replies Latest reply on Aug 7, 2007 6:56 PM by icordoba

    Entity relationship and remove operations

    strunker

      Hello,

      I have a problem with entity relationships and foreign key constraints. I want to get all child entities deleted when the parent entity is deleted. Therefore I used the CasecadeType.REMOVE, but it doesn't work.

      Here is code fragment:

      @Entity
      @Table(name = "Users")
      public class User implements Serializable {
      
       private int id;
      
       private List<ChatMessage> sentChatMessages;
       private List<ChatMessage> receivedChatMessages;
      
       @Id
       @GeneratedValue(strategy = GenerationType.IDENTITY)
       @Column(name = "id", updatable = false, nullable = false)
       public int getId() {
       return id;
       }
      
       @OneToMany(mappedBy = "sender", cascade = {CascadeType.REMOVE}, fetch = FetchType.LAZY)
       public List<ChatMessage> getSentChatMessages() {
       return this.sentChatMessages;
       }
      
       public void setSentChatMessages(List<ChatMessage> sentChatMessages) {
       this.sentChatMessages = sentChatMessages;
       }
      
       @OneToMany(mappedBy = "receipient", cascade = {CascadeType.REMOVE}, fetch = FetchType.LAZY)
       public List<ChatMessage> getReceivedChatMessages() {
       return this.receivedChatMessages;
       }
      
       public void setReceivedChatMessages(List<ChatMessage> receivedChatMessages) {
       this.receivedChatMessages = receivedChatMessages;
       }
      }
      


      @Entity
      @Table(name = "ChatMessages")
      public class ChatMessage implements Serializable {
      
       private User sender;
      
       private User receipient;
      
       private String message;
      
       @ManyToOne()
       @JoinColumn(name = "sender", referencedColumnName = "id", nullable = false)
       public User getSender() {
       return this.sender;
       }
      
       public void setSender(User sender) {
       this.sender = sender;
       }
      
       @ManyToOne()
       @JoinColumn(name = "receipient", referencedColumnName = "id", nullable = false)
       public User getReceipient() {
       return this.receipient;
       }
      
       public void setReceipient(User receipient) {
       this.receipient = receipient;
       }
      }
      


      When I try to delete a user, I exspect that all his messages are also deleted, but this does not happen. Instead I get the following exception:

      12:12:43,703 ERROR [JDBCExceptionReporter] ERROR: update or delete on "users" violates foreign key constraint "fk278c74e4eedef195" on "chatmessages"
      Detail: Key (id)=(12) is still referenced from table "chatmessages".
      12:12:43,703 ERROR [AbstractFlushingEventListener] Could not synchronize database state with session
      org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update
      at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:71)
      at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43)
      at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:249)
      at org.hibernate.jdbc.AbstractBatcher.prepareStatement(AbstractBatcher.java:92)
      at org.hibernate.jdbc.AbstractBatcher.prepareStatement(AbstractBatcher.java:87)
      at org.hibernate.jdbc.AbstractBatcher.prepareBatchStatement(AbstractBatcher.java:218)
      at org.hibernate.persister.entity.AbstractEntityPersister.delete(AbstractEntityPersister.java:2414)
      at org.hibernate.persister.entity.AbstractEntityPersister.delete(AbstractEntityPersister.java:2632)
      at org.hibernate.action.EntityDeleteAction.execute(EntityDeleteAction.java:73)
      at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:248)
      at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:232)
      at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:144)
      at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:298)
      at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)
      at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1000)
      at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:338)
      at org.hibernate.ejb.AbstractEntityManagerImpl$1.beforeCompletion(AbstractEntityManagerImpl.java:515)
      at org.jboss.tm.TransactionImpl.doBeforeCompletion(TransactionImpl.java:1491)
      at org.jboss.tm.TransactionImpl.beforePrepare(TransactionImpl.java:1110)
      at org.jboss.tm.TransactionImpl.commit(TransactionImpl.java:324)
      at org.jboss.tm.TxManager.commit(TxManager.java:240)
      at org.jboss.aspects.tx.TxPolicy.endTransaction(TxPolicy.java:175)
      at org.jboss.aspects.tx.TxPolicy.invokeInOurTx(TxPolicy.java:87)
      at org.jboss.aspects.tx.TxInterceptor$Required.invoke(TxInterceptor.java:191)
      at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
      at org.jboss.aspects.tx.TxPropagationInterceptor.invoke(TxPropagationInterceptor.java:76)
      at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
      at org.jboss.ejb3.stateless.StatelessInstanceInterceptor.invoke(StatelessInstanceInterceptor.java:62)
      at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
      at org.jboss.aspects.security.AuthenticationInterceptor.invoke(AuthenticationInterceptor.java:77)
      at org.jboss.ejb3.security.Ejb3AuthenticationInterceptor.invoke(Ejb3AuthenticationInterceptor.java:102)
      at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
      at org.jboss.ejb3.ENCPropagationInterceptor.invoke(ENCPropagationInterceptor.java:47)
      at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
      at org.jboss.ejb3.asynchronous.AsynchronousInterceptor.invoke(AsynchronousInterceptor.java:106)
      at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
      at org.jboss.ejb3.stateless.StatelessContainer.dynamicInvoke(StatelessContainer.java:263)
      at org.jboss.aop.Dispatcher.invoke(Dispatcher.java:106)
      at org.jboss.aspects.remoting.AOPRemotingInvocationHandler.invoke(AOPRemotingInvocationHandler.java:82)
      at org.jboss.remoting.ServerInvoker.invoke(ServerInvoker.java:828)
      at org.jboss.remoting.ServerInvoker.invoke(ServerInvoker.java:681)
      at org.jboss.remoting.transport.socket.ServerThread.processInvocation(ServerThread.java:358)
      at org.jboss.remoting.transport.socket.ServerThread.dorun(ServerThread.java:412)
      at org.jboss.remoting.transport.socket.ServerThread.run(ServerThread.java:239)
      Caused by: java.sql.BatchUpdateException: Batch-Eintrag 0 delete from Users where id=12 wurde abgebrochen. Rufen Sie getNextException auf, um die Ursache zu erfahren.
      at org.postgresql.jdbc2.AbstractJdbc2Statement$BatchResultHandler.handleError(AbstractJdbc2Statement.java:2478)
      at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1298)
      at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:347)
      at org.postgresql.jdbc2.AbstractJdbc2Statement.executeBatch(AbstractJdbc2Statement.java:2540)
      at org.jboss.resource.adapter.jdbc.WrappedStatement.executeBatch(WrappedStatement.java:519)
      at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:48)
      at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:242)
      ... 41 more

      What can I do? I tried to remove all user's messages with the entityManager before removing the user, but I had no luck.

      I use JBoss 4.0.5 and a Postgres 8.1 database.

        • 1. Re: Entity relationship and remove operations
          strunker

          Nobody an idea?

          • 2. Re: Entity relationship and remove operations
            oskar.carlstedt

            Hi!!

            I'm not sure about this. But I think I've read that you cannot specify booth name and referenceColumn when using the JoinColumn annotation.

            Try to just use the name attribute.

            //Oskar

            • 3. Re: Entity relationship and remove operations
              strunker

              Thanks for your reply.

              I tried it out. I removed the name and/or the referencedColumn, but it didn't work.

              • 4. Re: Entity relationship and remove operations

                Have you looked up which entity the error message refers to and to which constraint?

                Another problem might be that your entityManager is not in sync with the database.


                Regards

                Felix

                • 5. Re: Entity relationship and remove operations
                  strunker

                   

                  "fhh" wrote:
                  Have you looked up which entity the error message refers to and to which constraint?

                  Another problem might be that your entityManager is not in sync with the database.


                  Regards

                  Felix


                  Hi Felix,

                  the error message refers to member sender of entity ChatMessage. I looked up the constraint in my database and there it says:

                  CONSTRAINT fk278c74e4b6f3dc65 FOREIGN KEY (sender)
                   REFERENCES users (id) MATCH SIMPLE
                   ON UPDATE NO ACTION ON DELETE NO ACTION,
                  


                  I wonder about "ON DELETE NO ACTION". Shouldn't it be "ON DELETE CASCADE"?

                  • 6. Re: Entity relationship and remove operations
                    strunker

                    Hi!

                    I've just altered the table to enable cascading:

                    CONSTRAINT fk278c74e4b6f3dc65 FOREIGN KEY (sender)
                     REFERENCES users (id) MATCH SIMPLE
                     ON UPDATE NO ACTION ON DELETE CASCADE,
                    


                    And now deleting users works fine, but why is the schema not created automatically this way?

                    • 7. Re: Entity relationship and remove operations

                       


                      And now deleting users works fine, but why is the schema not created automatically this way?


                      I'm not sure whether javax persitence uses the on delete cascade functionality of the underlying database or whether the entitymanager will "manually" delete ferenced entities.

                      Regards

                      Felix

                      • 8. Re: Entity relationship and remove operations
                        strunker

                         

                        "fhh" wrote:

                        And now deleting users works fine, but why is the schema not created automatically this way?


                        I'm not sure whether javax persitence uses the on delete cascade functionality of the underlying database or whether the entitymanager will "manually" delete ferenced entities.

                        Regards

                        Felix


                        Does anybody here know these details and can me tell what to do now? Manually altering the database after deployment cannot be a real solution.

                        • 9. Re: Entity relationship and remove operations
                          jantzen

                          I'm facing a similar problem with child entities not being deleted with their parents. The exception I see is "javax.persistence.EntityNotFoundException: deleted entity passed to persist", and it looks like the entity manager is trying to persist the child entities with null references to the parent. I have CascadeType.ALL set on that relationship.

                          I'd be very disappointed to learn that manual deletion of child entities or database-level cascades were necessary, as the whole point of the JPA cascade functionality is to avoid that. But, I don't have a better answer yet. (BTW, I'm also on jboss 4.0.5 and postgres 8.1; it's bizarre that you're hitting a constraint violation and I'm not even getting that far).

                          • 10. Re: Entity relationship and remove operations

                            When I said the entity manager deletes the children manually I did not mean to say that _you_ as developer have to do it. What I meant to say is that instead of using "on delete cascade" on the constraint the entity manager might send a delete statement for every child to the database.

                            Regards

                            Felix

                            • 11. Re: Entity relationship and remove operations
                              strunker

                               

                              "fhh" wrote:
                              Another problem might be that your entityManager is not in sync with the database.


                              You were right. I simply had to refresh the parent and then hibernate could delete all references. So it's working now.

                              Conclusion: Hibernate does the cascading delete itself and does not use database features for that.

                              • 12. Re: Entity relationship and remove operations
                                icordoba

                                Hi there,
                                I haven't been able to solve this same problem ("deleted entity passed to persist" exception when deleting a OneToMany with cascade all relation(). You say you just have to "refresh" the parent, but you were saying that you delete the parent and you expect the children to be deleted. If you delete the parent, how do you refresh it? (I get "Not managed entity" if I try to em.refresh() it)

                                Thanks for any help,
                                Ignacio