# @AuditJoinTable in Envers

**URL:** <https://discourse.hibernate.org/t/auditjointable-in-envers/3445>\
**Category:** Hibernate ORM\
**Created:** [November 15, 2019, 3:33am UTC](https://discourse.hibernate.org/t/auditjointable-in-envers/3445 "2019-11-15T03:33:01Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![sreejesh](https://avatars.discourse-cdn.com/v4/letter/s/9de0a6/32.png) [@sreejesh](https://discourse.hibernate.org/u/sreejesh)\
**Post date:** [November 15, 2019, 3:33am UTC](https://discourse.hibernate.org/t/auditjointable-in-envers/3445/1 "2019-11-15T03:33:01Z")

</div>

Hi @Naros, Why Hibernate Envers uses an @AuditJoinTable for @OneToMany+@JoinColumn? Why audit tables of parent & child entities are not sufficient for auditing?

---

<div class="post-metadata">

**Author:** ![Naros](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.hibernate.org/naros/32/19_2.png) [@Naros](https://discourse.hibernate.org/u/Naros)\
**Post date:** [November 15, 2019, 4:09pm UTC](https://discourse.hibernate.org/t/auditjointable-in-envers/3445/2 "2019-11-15T16:09:49Z")

</div>

To be clear, you have a mapping such as the following:

```
@Entity
@Audited
public class Company {
  @Id
  private Integer id;
  @OneToMany
  @JoinColumn
  private List<Employee> employees;
}

@Entity
@Audited
public class Employee {
  @Id
  private Integer id;
}

```

In order to understand why Envers builds the mappings the way it does I believe its important to look at how ORM handles this use case first. If we look at the `Employee` table generated by ORM we’ll see:

```
CREATE TABLE Employee (
  id integer not null,
  company_id integer,
  employees_id integer,
  primary key(id)
);

```

As we can see, ORM embeds the `@JoinColumn` attributes as a part of `Employee`.

Lets now look at this from the perspective of Envers. Unfortunately Envers cannot work the way that ORM does for this mapping because we have to be cautious about audit record bloat. We want to keep the number of rows generated per change manageable but also keeping audit rows relevant.

What I mean is, without the middle join-table, Envers would be required to generate an audit row for every associated `Employee` record inside the employees collection for a `Company` entity, even if all that changed on `Company` was some superficial attribute, say like its name or something silly like that.

By using a middle-join table

1. Envers can manage changes for both entity types independently
2. Auditing employees collection involves managing just foreign-key state changes
3. Avoids needing to load unnecessary entity state just to build an audit row.

If you want to avoid the middle join-table here, its best to use `mappedBy=...` on the `@OneToMany` in conjunction with a `@ManyToOne` on the owning side of the relationship, then Envers will build and operate on the associate in the same exact way as ORM.

Hope that answers your question.

---

<div class="post-metadata">

**Author:** ![GeraldoOfTheRiviera](https://avatars.discourse-cdn.com/v4/letter/g/91b2a8/32.png) [@GeraldoOfTheRiviera](https://discourse.hibernate.org/u/GeraldoOfTheRiviera)\
**Post date:** [June 10, 2020, 1:54pm UTC](https://discourse.hibernate.org/t/auditjointable-in-envers/3445/3 "2020-06-10T13:54:16Z")

</div>

The explanation you gave was great. Much better than the one on the official docs… which seems to be contradicting or even completely different from your explanation:

[https://docs.jboss.org/envers/docs/#exceptions-onetomanyjoincolumn](https://docs.jboss.org/envers/docs/#exceptions-onetomanyjoincolumn)

According to the docs, the middle-join table is created so “when you read the revisions in which the related entity has changed, you don’t get false results”. The docs aren’t very clear here imo. But it seems to be a different reason from the one you gave, which was, if I understood correctly: using the middle-join table makes things easier and more efficient for envers.

Or am I missing something? Thanks.
