5 Replies Latest reply on Jan 26, 2010 8:56 AM by Adam Warski

    @ManyToOne+@JoinColumn Error

    djabornig Newbie

      I try to delete an entity with an unidirectional OneToMany Relationship mapped like this:

       

      @Entity
      @Table(name = "TEST_SOURCE_ENTITY")
      @Audited
      public class SourceEntity extends GenericEntity<Long> {
      
           @OneToMany(fetch = FetchType.EAGER)
           @JoinColumn(name = "SOURCE_ENTITY_UNI_ID")
           @Cascade(value = { org.hibernate.annotations.CascadeType.ALL,
                     org.hibernate.annotations.CascadeType.DELETE_ORPHAN })
           @org.hibernate.annotations.IndexColumn(name = "SOURCE_ENTITY_UNI_IDX")
           @AuditJoinTable(name = "TEST_SOURCE_TARGET_ENTITY_AUD")
           private List<TargetEntity> unidirectionalTargetEntities = new ArrayList<TargetEntity>();
      
           public List<TargetEntity> getUnidirectionalTargetEntities() {
                return unidirectionalTargetEntities;
           }
      
           public void setUnidirectionalTargetEntities(
                     List<TargetEntity> unidirectionalTargetEntities) {
                this.unidirectionalTargetEntities = unidirectionalTargetEntities;
           }
      }
      
      @Entity
      @Table(name = "TEST_TARGET_ENTITY")
      @Audited
      public class TargetEntity extends GenericEntity<Long> {
      
           private static final long serialVersionUID = 1L;
           
      }
      

       

      On delete envers tries to set a null value on the inverse join column.

       

      SourceEntity sourceEntity = ...
      session.delete(sourceEntity);
      

       

      And this exception is the result...

       

      
      Caused by: java.sql.BatchUpdateException: ORA-01400: Einfügen von NULL in ("TEST"."TEST_SOURCE_TARGET_ENTITY_AUD"."ID") nicht möglich
      
           at oracle.jdbc.driver.DatabaseError.throwBatchUpdateException(DatabaseError.java:343)
           at oracle.jdbc.driver.OraclePreparedStatement.executeBatch(OraclePreparedStatement.java:10768)
           at org.apache.commons.dbcp.DelegatingPreparedStatement.executeBatch(DelegatingPreparedStatement.java:231)
           at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:70)
           at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:268)
           ... 49 more
      

      I tried already a lot of things and if i make the relationship bidirectional it seems to work.

       

      The same issue occurs if i map the relationship with @OneToMany+@JoinColumn on the one side, and @ManyToOne+@JoinColumn(insertable=false, updatable=false)

       

      What am i doing wrong here? I'm using the current envers 1.2.2. in the maven repo.

        • 1. Re: @ManyToOne+@JoinColumn Error
          Adam Warski Master

          It's hard to say anything without a test case ... maybe this is because of the delete orphan, did you try to remove that?

           

          Also, to make the @OneToMany+@JoinColumn / @ManyToOne+@JoinColumn(insertable=false, updatable=false) combination work, you also need to add an @AuditMappedBy annotation on the one side.

           

          Adam

          • 2. Re: @ManyToOne+@JoinColumn Error
            djabornig Newbie

            Thanks for your answer Adam.

             

            Removing the delete-orphan has not effect. In fact because of the call session.delete(), the delete cascade is the problem.

             

            On cascade delete envers tries to insert the following rows in the join-table and audit tables:

             

            Hibernate: 
                insert 
                into
                    TEST_SOURCE_TARGET_ENTITY_AUD
                    (REVTYPE, REV, SOURCE_ENTITY_UNI_ID, ID, SOURCE_ENTITY_UNI_IDX) 
                values
                    (2, 55, 54, null (should be 53), 0)
            Hibernate: 
                insert 
                into
                    TEST_TARGET_ENTITY_AUD
                    (REVTYPE, ID, REV) 
                values
                    (2, 53, 55)
            Hibernate: 
                insert 
                into
                    TEST_SOURCE_ENTITY_AUD
                    (REVTYPE, ID, REV) 
                values
                    (2, 54, 55)
            

             

            On TEST_SOURCE_TARGET_ENTITY_AUD there are not null constraints created for all columns except REVTYPE. If i deactivate the constraints the delete works of course. Because i dont read the deleted entities this may be an acceptable workaround. But the created audit data for the delete statement is wrong.

            • 3. Re: @ManyToOne+@JoinColumn Error
              Adam Warski Master

              Hmm, this looks like a bug, although it's quite weird, as I think that this case is covered by tests.

              Could you create a unit test and a jira issue?

               

              Adam

              • 4. Re: @ManyToOne+@JoinColumn Error
                djabornig Newbie
                Just when i was creating the test case i found out what causes the problem.

                 

                I have indentifier rollback enabled. This causes the null values.

                 

                config.setProperty("hibernate.use_identifier_rollback", "true");

                 

                I created an issue with test case:

                http://opensource.atlassian.com/projects/hibernate/browse/HHH-4842

                 

                Is there any workaround for this except to disable identifier rollback?

                • 5. Re: @ManyToOne+@JoinColumn Error
                  Adam Warski Master

                  Ah, so if you have hibernate.use_identifier_rollback set to true, then the new value of the join column will be null, so envers simply copies this. One workaround would be to use the @AuditMappedBy annotation and not use the join table. But then, of course, the audit table will hold a null value for the foreign key after a delete, just as the normal table.

                   

                  Adam