# Envers: create multiple revisions in one transaction

**URL:** <https://discourse.hibernate.org/t/envers-create-multiple-revisions-in-one-transaction/5138>\
**Category:** Hibernate ORM\
**Created:** [March 4, 2021, 7:21pm UTC](https://discourse.hibernate.org/t/envers-create-multiple-revisions-in-one-transaction/5138 "2021-03-04T19:21:33Z")\
**Posts on this page:** 18\
**Page:** 1

<div class="post-metadata">

**Author:** ![Frank\_Hagemann](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.hibernate.org/frank_hagemann/32/1419_2.png) [@Frank\_Hagemann](https://discourse.hibernate.org/u/Frank_Hagemann)\
**Post date:** [March 4, 2021, 7:21pm UTC](https://discourse.hibernate.org/t/envers-create-multiple-revisions-in-one-transaction/5138/1 "2021-03-04T19:21:33Z")

</div>

Hello everybody,

I have a running application using envers and I am facing the following problem:  
My entity should track a functional status value to retrieve the history of modifications. I apply these steps to the entity:

1. set current version to “outdated”
2. update the entity from by calling an external resource

This should result in 3 audit records:  
Rev #1: consistent  
Rev #2: outdated  
Rev #3 consistent

When I summarize both steps into one transaction Rev #2 gets lost.

I’ve tracked down that envers creates only one revision at transaction.commit() - thats what I understood is a architectural decision.

Is there a possibility to force creation of an revision on a flush() to track consistently all modifications in one transaction?

When I split the steps into 2 transactions everything works smooth. My goal is to put both operations into 1 transaction. By doing this Rev#2 gets lost.  
When I split both operations into seperate transactions everything works fine. Do you have an idea how to achieve this behaviour with envers within 1 single transaction?

Frank

---

<div class="post-metadata">

**Author:** ![beikov](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.hibernate.org/beikov/32/258_2.png) [@beikov](https://discourse.hibernate.org/u/beikov)\
**Post date:** [March 5, 2021, 8:19am UTC](https://discourse.hibernate.org/t/envers-create-multiple-revisions-in-one-transaction/5138/2 "2021-03-05T08:19:01Z")

</div>

Hibernate Envers, as you figured, only creates the revisions before transaction commit. You could try to invoke the pre commit listener manually by using `AuditProcessManager.get(session).doBeforeTransactionCompletion(session)` but I haven’t tried that myself yet.

---

<div class="post-metadata">

**Author:** ![Frank\_Hagemann](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.hibernate.org/frank_hagemann/32/1419_2.png) [@Frank\_Hagemann](https://discourse.hibernate.org/u/Frank_Hagemann)\
**Post date:** [March 5, 2021, 9:55am UTC](https://discourse.hibernate.org/t/envers-create-multiple-revisions-in-one-transaction/5138/3 "2021-03-05T09:55:11Z")

</div>

Thank you for your tip. But I couldn’t find out how to access the AuditProcessManager. Can you explain me how to access it?

---

<div class="post-metadata">

**Author:** ![beikov](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.hibernate.org/beikov/32/258_2.png) [@beikov](https://discourse.hibernate.org/u/beikov)\
**Post date:** [March 5, 2021, 11:32am UTC](https://discourse.hibernate.org/t/envers-create-multiple-revisions-in-one-transaction/5138/4 "2021-03-05T11:32:52Z")

</div>

You need something like this `sessionFactory.getServiceRegistry().getService(EnversService.class).getAuditProcessManager()`

---

<div class="post-metadata">

**Author:** ![mzeher](https://avatars.discourse-cdn.com/v4/letter/m/fbc32d/32.png) [@mzeher](https://discourse.hibernate.org/u/mzeher)\
**Post date:** [July 29, 2021, 4:33pm UTC](https://discourse.hibernate.org/t/envers-create-multiple-revisions-in-one-transaction/5138/5 "2021-07-29T16:33:53Z")

</div>

Hello,  
I am facing the same problem - I need to make more updates of audited entity in one transaction and need to have record in audit table for each update. Is there meanwhile more information to the topic?  
I’m not sure if I got the hint with _AuditProcessManager.get(session).doBeforeTransactionCompletion(session)_ right? Should I try to trigger it from the code at the time when I want to create new audit record? (In my case after each update?)

---

<div class="post-metadata">

**Author:** ![beikov](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.hibernate.org/beikov/32/258_2.png) [@beikov](https://discourse.hibernate.org/u/beikov)\
**Post date:** [July 30, 2021, 8:46am UTC](https://discourse.hibernate.org/t/envers-create-multiple-revisions-in-one-transaction/5138/6 "2021-07-30T08:46:47Z")

</div>

Yeah, you understood that correctly.

---

<div class="post-metadata">

**Author:** ![mzeher](https://avatars.discourse-cdn.com/v4/letter/m/fbc32d/32.png) [@mzeher](https://discourse.hibernate.org/u/mzeher)\
**Post date:** [July 30, 2021, 9:26am UTC](https://discourse.hibernate.org/t/envers-create-multiple-revisions-in-one-transaction/5138/7 "2021-07-30T09:26:09Z")

</div>

I tried this:

```auto
private void forceCreateEnversAudition() {
        Session hibernateSession = this.entityManager.unwrap(Session.class);
        SessionFactory sessionFactory = hibernateSession.getSessionFactory();
        AuditProcessManager apm = sessionFactory.getSessionFactory().getServiceRegistry().getService(EnversService.class).getAuditProcessManager();
        apm.get( **session** ).doBeforeTransactionCompletion( **session** );
    }

```

The input parameter _session_ of the method AuditProsessManager.get(EventSource session) is of type EventSource (I thought it was Session at first). I have no idea what should I provide there.

---

<div class="post-metadata">

**Author:** ![beikov](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.hibernate.org/beikov/32/258_2.png) [@beikov](https://discourse.hibernate.org/u/beikov)\
**Post date:** [July 30, 2021, 10:19am UTC](https://discourse.hibernate.org/t/envers-create-multiple-revisions-in-one-transaction/5138/8 "2021-07-30T10:19:58Z")

</div>

The session implements that interface, you can cast the session.

---

<div class="post-metadata">

**Author:** ![mzeher](https://avatars.discourse-cdn.com/v4/letter/m/fbc32d/32.png) [@mzeher](https://discourse.hibernate.org/u/mzeher)\
**Post date:** [July 30, 2021, 11:05am UTC](https://discourse.hibernate.org/t/envers-create-multiple-revisions-in-one-transaction/5138/9 "2021-07-30T11:05:27Z")

</div>

Ah, I see, thanks 🙂

I called this:

```auto
 private void forceCreateEnversAudition() {
        Session hibernateSession = this.entityManager.unwrap(Session.class);
        SessionFactory sessionFactory = hibernateSession.getSessionFactory();
        AuditProcessManager apm = ((SessionFactoryImplementor) sessionFactory).getServiceRegistry().getService(EnversService.class).getAuditProcessManager();
        apm.get((EventSource) hibernateSession).doBeforeTransactionCompletion((SessionImplementor) hibernateSession);
    }

```

after this.entityManager.persist() and after corresponding entity properties change in case of update, but see no change - only 1 record in audition table.

---

<div class="post-metadata">

**Author:** ![beikov](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.hibernate.org/beikov/32/258_2.png) [@beikov](https://discourse.hibernate.org/u/beikov)\
**Post date:** [July 30, 2021, 11:17am UTC](https://discourse.hibernate.org/t/envers-create-multiple-revisions-in-one-transaction/5138/10 "2021-07-30T11:17:39Z")

</div>

Did you call `hibernateSession.flush()` before?

---

<div class="post-metadata">

**Author:** ![mzeher](https://avatars.discourse-cdn.com/v4/letter/m/fbc32d/32.png) [@mzeher](https://discourse.hibernate.org/u/mzeher)\
**Post date:** [July 30, 2021, 11:19am UTC](https://discourse.hibernate.org/t/envers-create-multiple-revisions-in-one-transaction/5138/11 "2021-07-30T11:19:14Z")

</div>

Yes, I tried both with and without flush.

---

<div class="post-metadata">

**Author:** ![mzeher](https://avatars.discourse-cdn.com/v4/letter/m/fbc32d/32.png) [@mzeher](https://discourse.hibernate.org/u/mzeher)\
**Post date:** [July 30, 2021, 11:19am UTC](https://discourse.hibernate.org/t/envers-create-multiple-revisions-in-one-transaction/5138/12 "2021-07-30T11:19:54Z")

</div>

this.entityManager.flush()

---

<div class="post-metadata">

**Author:** ![beikov](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.hibernate.org/beikov/32/258_2.png) [@beikov](https://discourse.hibernate.org/u/beikov)\
**Post date:** [July 30, 2021, 11:32am UTC](https://discourse.hibernate.org/t/envers-create-multiple-revisions-in-one-transaction/5138/13 "2021-07-30T11:32:09Z")

</div>

AFAICT this should cause the creation of `AuditWorkUnit`. If that doesn’t work, then this simply can’t be done right now. Chances are, it is possible but there is some other problem with how you try to use it. Maybe you can debug this a bit to understand where this might go wrong.

---

<div class="post-metadata">

**Author:** ![mzeher](https://avatars.discourse-cdn.com/v4/letter/m/fbc32d/32.png) [@mzeher](https://discourse.hibernate.org/u/mzeher)\
**Post date:** [July 30, 2021, 1:27pm UTC](https://discourse.hibernate.org/t/envers-create-multiple-revisions-in-one-transaction/5138/14 "2021-07-30T13:27:14Z")

</div>

After little debugging I found out following:

- the saving of audit entity was triggered _AuditStrategy.perform()_ was called

- in database table I could see the audit record with correct values

- at the end of the transaction, the same audit record contained new values - it was updated =\> only 1 audit record per audited entity and transaction in audit table

---

<div class="post-metadata">

**Author:** ![beikov](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.hibernate.org/beikov/32/258_2.png) [@beikov](https://discourse.hibernate.org/u/beikov)\
**Post date:** [July 30, 2021, 1:51pm UTC](https://discourse.hibernate.org/t/envers-create-multiple-revisions-in-one-transaction/5138/15 "2021-07-30T13:51:27Z")

</div>

Hmm, that is unfortunate. I don’t know where this happens or if this can be worked around. Maybe you can get around this if you invoke the `afterTransactionCompletion` on `SessionImplementor`, but I don’t know what effects this will have on the rest of the transaction.

---

<div class="post-metadata">

**Author:** ![mzeher](https://avatars.discourse-cdn.com/v4/letter/m/fbc32d/32.png) [@mzeher](https://discourse.hibernate.org/u/mzeher)\
**Post date:** [July 30, 2021, 2:21pm UTC](https://discourse.hibernate.org/t/envers-create-multiple-revisions-in-one-transaction/5138/16 "2021-07-30T14:21:41Z")

</div>

I 've added this call at the end of the method:

```auto
private void forceCreateEnversAudition() {
        this.entityManager.flush();
        Session hibernateSession = this.entityManager.unwrap(Session.class);
        SessionFactory sessionFactory = hibernateSession.getSessionFactory();
        AuditProcessManager apm = ((SessionFactoryImplementor) sessionFactory).getServiceRegistry().getService(EnversService.class).getAuditProcessManager();
        apm.get((EventSource) hibernateSession).doBeforeTransactionCompletion((SessionImplementor) hibernateSession);
        **((SessionImplementor) hibernateSession).afterTransactionCompletion(true, false);**
    }

```

At first glance it looks fine - i can see also the previous versions in audit table, each has new REV number.

---

<div class="post-metadata">

**Author:** ![joern](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.hibernate.org/joern/32/4072_2.png) [@joern](https://discourse.hibernate.org/u/joern)\
**Post date:** [July 9, 2025, 8:38pm UTC](https://discourse.hibernate.org/t/envers-create-multiple-revisions-in-one-transaction/5138/17 "2025-07-09T20:38:15Z")

</div>

Just for information: the workaround from mzeher is still working in 2025. I only had to get the `SessionImpl.class` from the `entityManager` as getting the `Session.class` got me a proxy that I couldn’t cast to `SessionImplementor` or `EventSource`:

```auto
    private void forceCreateEnversAudition() {
        this.entityManager.flush();
        SessionImpl hibernateSession = this.entityManager.unwrap(SessionImpl.class);
        SessionFactoryImplementor sessionFactory = hibernateSession.getSessionFactory();
        AuditProcessManager apm = sessionFactory.getServiceRegistry()
                    .getService(EnversService.class)
                    .getAuditProcessManager();
        apm.get(hibernateSession)
                    .doBeforeTransactionCompletion(hibernateSession);
        hibernateSession.afterTransactionCompletion(true, false);
    }

```

---

<div class="post-metadata">

**Author:** ![beikov](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.hibernate.org/beikov/32/258_2.png) [@beikov](https://discourse.hibernate.org/u/beikov)\
**Post date:** [July 10, 2025, 3:50pm UTC](https://discourse.hibernate.org/t/envers-create-multiple-revisions-in-one-transaction/5138/18 "2025-07-10T15:50:24Z")

</div>

It might be worth adding a `FlushEventListener` for Hibernate Envers that does this automatically when you call `session.flush()`. Registration of that listener would happen through `EnversIntegrator`. Contributions are welcome.
