title: Composite table with Hibernate Envers
body: <p>I have an application with a composite table holding one extra column. It all works fine, until we add Hibernate Envers (@Audited).</p>
  
  <blockquote>
    <p>org.hibernate.MappingException: Unable to read the mapped by attribute for responseDomainCodes in no.pack.response.ResponseDomainCode</p>
  </blockquote>
  
  <p>I am happy to provide more detailed information if necessary, however, at this time I am not sure what would be relevant.</p>
  
  <p>The tables look like this, and is a pretty standard composite key table, with one extra column.</p>
  
  <p><strong>Database schema</strong></p>
  
  <pre><code>+-----------+---------+
  |   CODE    |  TYPE   |
  +-----------+---------+
  | category  | VARCHAR |
  | code      | VARCHAR |
  +-----------+---------+
              |
              |
  +----------------------+---------+
  | RESPONSE_DOMAIN_CODE |  TYPE   |
  +----------------------+---------+
  | response_domain_id   | KEY     |
  | code_id              | KEY     |
  | rank                 | VARCHAR |
  +----------------------+---------+
              |
              |
  +--------------------+------+
  |  RESPONSE_DOMAIN   | TYPE |
  +--------------------+------+
  | response_domain_id | PK   |
  | response_kind_id   | FK   |
  +--------------------+------+
  </code></pre>
  
  <p><strong>ResponseDomain.java</strong></p>
  
  <pre><code>@Entity
  @Table(name = "responseDomain")
  public class ResponseDomain implements Serializable {
  
      @Id
      @Column(name = "responseDomain_id")
      @GeneratedValue(strategy = GenerationType.AUTO)
      private Long id;
  
     @ManyToOne
     @JoinColumn(name = "respons_kind_id")
     private ResponseKind responseKind;
  
     @OneToMany(fetch = FetchType.EAGER, mappedBy = "pk.responseDomain",  cascade = CascadeType.ALL)
      private Set&lt;ResponseDomainCode&gt; responseDomainCodes = new HashSet&lt;&gt;();
  
   //Omitted rest.
  }
  </code></pre>
  
  <p><strong>Code.java</strong></p>
  
  <pre><code>@Entity
  @Table(name = "code")
  public class Code implements Serializable {
  
      @Id
      @Column(name = "code_id")
      @GeneratedValue(strategy = GenerationType.AUTO)
      private Long id;
  
      private String category;
  
      private  String code;
  
      @OneToMany(fetch = FetchType.EAGER, mappedBy = "pk.code", cascade = CascadeType.ALL)
      private Set&lt;ResponseDomainCode&gt; responseDomainCodes = new HashSet&lt;&gt;();
  
      //Omitted rest
  }
  </code></pre>
  
  <p><strong>ResponseDomainCode.java</strong></p>
  
  <pre><code>@Entity
  @Table(name = "responseDomain_code")
  @AssociationOverrides(value = {
          @AssociationOverride(name = "pk.responseDomain",
                  joinColumns = @JoinColumn(name = "responseDomain_id")),
          @AssociationOverride(name = "pk.code",
                  joinColumns = @JoinColumn(name = "code_id"))
  })
  public class ResponseDomainCode implements Serializable {
  
      @EmbeddedId
      private ResponseDomainCodeId pk = new ResponseDomainCodeId();
  
      @Column(name = "rank")
      private String rank;
  
      public ResponseDomainCodeId getPk() {
          return pk;
      }
  
      public void setPk(ResponseDomainCodeId pk) {
          this.pk = pk;
      }
  
      public String getRank() {
          return rank;
      }
  
      public void setRank(String rank) {
          this.rank = rank;
      }
  
      @Transient
      public ResponseDomain getResponseDomain() {
          return getPk().getResponseDomain();
      }
  
      public void setResponseDomain(ResponseDomain responseDomain) {
          this.getPk().setResponseDomain(responseDomain);
      }
  
      @Transient
      public Code getCode() {
          return getPk().getCode();
      }
  
      public void setCode(Code code) {
          this.getPk().setCode(code);
      }
  
      //Omitted rest
  }
  </code></pre>
  
  <p><strong>ResponseDomainCodeId.java</strong></p>
  
  <pre><code>@Embeddable
  public class ResponseDomainCodeId implements Serializable {
  
      @ManyToOne
      private ResponseDomain responseDomain;
  
      @ManyToOne
      private Code code;
  
      public ResponseDomainCodeId() {
      }
  
      public ResponseDomain getResponseDomain() {
          return responseDomain;
      }
  
      public void setResponseDomain(ResponseDomain responseDomain) {
          this.responseDomain = responseDomain;
      }
  
      public Code getCode() {
          return code;
      }
  
      public void setCode(Code code) {
          this.code = code;
      }
  
      //Omitted rest
  }
  </code></pre>