0

I have a parent child @OneToMany relation with the one side as owner. The relation is bidirectional.

The reference table ParentChild has a composite key (parentId, childId) and has an additional attribute name. All changes should be audited by envers, therefore we have chosen the owner side on the parent side that adding and removing a child creates a revision of the parent.

But generating the DDL throws the following exception:

rg.hibernate.MappingException: Repeated column in mapping for entity: com.comfone.audit.test.audittest.data.ParentChild_AUD column: parent_id (should be mapped with insert="false" update="false")

Envers tries to generate the ParentChild_AUD table containing the composite key and the audited fields but it also tries to add two columns parent_id and child_id which conflicts with the composite key.

Is this a bug or do I something wrong?

Thanks for your help!

Cheers Andy

Generated DDL:

<?xml version="1.0" encoding="UTF-8"?>
<hibernate-mapping auto-import="false">
 <class entity-name="com.comfone.audit.test.audittest.data.ParentChild_AUD" discriminator-value="ParentChild" table="parent_child_AUD" abstract="false">
  <composite-id name="originalId">
   <key-property name="childId" type="long">
    <column name="child_id" length="255" scale="2" precision="19"/>
   </key-property>
   <key-property name="parentId" type="long">
    <column name="parent_id" length="255" scale="2" precision="19"/>
   </key-property>
   <key-many-to-one type="integer" class="org.hibernate.envers.DefaultRevisionEntity" name="REV">
    <column name="REV"/>
   </key-many-to-one>
  </composite-id>
  <property insert="true" update="false" name="REVTYPE" type="org.hibernate.envers.internal.entities.RevisionTypeType"/>
  <property insert="true" update="false" name="name" type="string">
   <column name="name" length="255" scale="2" precision="19"/>
  </property>
  <property insert="false" update="false" name="child_id" type="long">
   <column name="child_id" length="255" scale="2" precision="19"/>
  </property>
  <property insert="true" update="false" name="parent_id" type="long">
   <column name="parent_id" length="255" scale="2" precision="19"/>
  </property>
 </class>
</hibernate-mapping>

Parent.java:

Entity
@Audited
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Getter
@Setter
@EqualsAndHashCode(of = {"id"})
public class Parent implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;

    @AuditMappedBy(mappedBy = "parent")
    @Builder.Default
    @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
    @JoinColumn(name = "PARENT_ID", insertable = false, updatable = false)
    private Set<ParentChild> parentChildren = new HashSet<>();

    @Version
    @Setter(AccessLevel.NONE)
    private Long version;

    public void addParentChild(ParentChild parentChild) {
        parentChild.setParent(this);
        this.parentChildren.add(parentChild);
    }

    public void removeParentChild(ParentChild parentChild) {
        parentChild.setParent(null);
        this.parentChildren.remove(parentChild);
    }
}

ParentChild.java:

@Entity
@Audited
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Getter
@Setter
@EqualsAndHashCode(of = {"parentChildId"})
public class ParentChild implements Serializable {

    @EmbeddedId
    private final ParentChildId parentChildId = new ParentChildId();

    private String name;

    @ManyToOne(optional = false, fetch = FetchType.LAZY)
    @MapsId("parentId")
    @JoinColumn(insertable = false, updatable = false)
    private Parent parent;

    @ManyToOne(optional = false, fetch = FetchType.LAZY)
    @MapsId("childId")
    @JoinColumn(insertable = false, updatable = false)
    private Child child;

    @Version
    @Setter(AccessLevel.NONE)
    private Long version;
}

Child.java:

@Entity
@Audited
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Getter
@Setter
@EqualsAndHashCode(of = {"id"})
public class Child {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;
}

Test project: https://github.com/hotkeeper/jpa-envers-test

It should not generate the two additional columns:

<?xml version="1.0" encoding="UTF-8"?>
<hibernate-mapping auto-import="false">
 <class entity-name="com.comfone.audit.test.audittest.data.ParentChild_AUD" discriminator-value="ParentChild" table="parent_child_AUD" abstract="false">
  <composite-id name="originalId">
   <key-property name="childId" type="long">
    <column name="child_id" length="255" scale="2" precision="19"/>
   </key-property>
   <key-property name="parentId" type="long">
    <column name="parent_id" length="255" scale="2" precision="19"/>
   </key-property>
   <key-many-to-one type="integer" class="org.hibernate.envers.DefaultRevisionEntity" name="REV">
    <column name="REV"/>
   </key-many-to-one>
  </composite-id>
  <property insert="true" update="false" name="REVTYPE" type="org.hibernate.envers.internal.entities.RevisionTypeType"/>
  <property insert="true" update="false" name="name" type="string">
   <column name="name" length="255" scale="2" precision="19"/>
  </property>
 </class>
</hibernate-mapping>

0 Answers0