6

My question can be trival, but documentation for hibernate-envers say I need just 2 steps to make hibernate envers work:

  1. the hibernate-envers jar on the classpath,

  2. an @Audited annotation on the entity.

First of all I added:

<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-envers</artifactId>
    <version>5.2.12.Final</version>
</dependency>

Second I added @Audited annotation above my entity:

@Entity
@Audited
@Table(name = "users")
public class User {...}

After those 2 steps I've got an option to:

  1. generate auto schema using the hbm2ddl tool

  2. create the schema alone.

A lot of ppl in tutorials/docs etc. says that you should do it alone so this is how my schema looks like (in thymeleaf).

To make schema manually I had to create changeset with one special table (usually called revinfo):

    <createTable tableName="revinfo">
        <column name="rev" type="integer">
            <constraints primaryKey="true"/>
        </column>
        <column name="revtstmp" type="bigint"></column>
    </createTable>

Now I just need to add new tables called tablename_AUD (ofc I can change this name by adding new annotation in my entity @AuditTable("new_name"), but it's not the case) with added rev and revtype column.

This is one of my existing tables in liquibase:

    <createTable tableName="users">
        <column name="id" type="int">
            <constraints primaryKey="true" nullable="false"/>
        </column>
        <column name="email" type="varchar(200)">
            <constraints unique="true" nullable="false"/>
        </column>
        <column name="first_name" type="varchar(60)">
            <constraints nullable="false"/>
        </column>
        <column name="last_name" type="varchar(60)">
            <constraints nullable="false"/>
        </column>
    </createTable>

So this is how my users_AUD looks like:

    <createTable tableName="users_AUD">
        <column name="id" type="bigint">
            <constraints primaryKey="true" nullable="false"/>
        </column>
        <column name="rev" type="bigint">
            <constraints referencedTableName="revinfo"
                         foreignKeyName="fk_users_AUD_revinfo"
                         referencedColumnNames="rev"
                         nullable="false"/>
        </column>
        <column name="revtype" type="smallint"/>
        <column name="email" type="varchar(200)">
            <constraints unique="true" nullable="false"/>
        </column>
        <column name="first_name" type="varchar(60)">
            <constraints nullable="false"/>
        </column>
        <column name="last_name" type="varchar(60)">
            <constraints nullable="false"/>
        </column>
    </createTable>

The question is: Why I have an ERROR:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaAutoConfiguration.class]: Invocation of init method failed; nested exception is java.lang.NoClassDefFoundError: org/hibernate/boot/registry/classloading/internal/ClassLoaderServiceImpl$Work

I added also entity manager depedency in my pom, but it didnt solve my problem.

Earlier called:

Such mapping is possible, but has to be explicitly defined using @Audited(targetAuditMode = NOT_AUDITED)

And answer from @ThomasEdwin helped me out. He said that we need to

add @Audited to all related entities.

Or like I noticed we can also annotate in our entity

@Audited(targetAuditMode = RelationTargetAuditMode.NOT_AUDITED).

A lot of similar questions are out-of-date (earlier there was much more needed to configure/set up envers, thats why I created new question).

update: After fixes with versions etc. finally app runs, but when I try to add an user by a POST I've got error like this:

https://pastebin.com/raw/d1vqY6xp

degath
  • 1,530
  • 4
  • 31
  • 60

1 Answers1

2

Such mapping is possible, but has to be explicitly defined using @Audited(targetAuditMode = NOT_AUDITED)

You need to add @Audited to all related entities.

Edit:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaAutoConfiguration.class]: Invocation of init method failed; nested exception is java.lang.NoClassDefFoundError: org/hibernate/boot/registry/classloading/internal/ClassLoaderServiceImpl$Work

This may help: Error creating bean with name 'entityManagerFactory' Invocation of init method failed. You need to make sure hibernate use the same version as pointed out by @naros.

ThomasEdwin
  • 2,035
  • 1
  • 24
  • 36
  • This can be a case (I wanted to just test it with a single entity, but I'll do it with all). And if I would've like to create those tables manually. I need to set up somewhere to not use automatic schema generation feature? – degath Dec 14 '17 at 10:51
  • Do you want to include envers schema to automatic schema generation? @degath – ThomasEdwin Dec 14 '17 at 10:52
  • I'm not sure yet. But I would like to know how to do both. (include and not include) – degath Dec 14 '17 at 10:55
  • If you use ant, you can use `EnversHibernateToolTask`. – ThomasEdwin Dec 14 '17 at 10:59
  • I'm not using ant. – degath Dec 14 '17 at 11:00
  • `I'm not using ant` then it should have been generated. See https://www.thoughts-on-java.org/hibernate-envers-getting-started/ – ThomasEdwin Dec 14 '17 at 11:02
  • let me clear my mind. To let audit work I need to get maven depedency, then mark entities as @Audited, and then create in my schema all tables manually with just _AUD suffix? – degath Dec 14 '17 at 11:02
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/161198/discussion-between-thomasedwin-and-degath). – ThomasEdwin Dec 14 '17 at 11:02
  • That message simply states that you either need to annotate the associated entity with `@Audited` or you need to mark the association in your single audited entity as `@Audited(targetAuditMode = NOT_AUDITED)` which means that Envers won't audit the associated entity type, but only the id. In other words, your single audited entity will always then point to real associated entity regardless of version. As for schema generation, just use `hibernate.hbm2ddl.auto=update` in order for the Envers tables to be created automatically. – Naros Dec 14 '17 at 13:59
  • @ThomasEdwin I updated a question to mark a real problem. – degath Dec 15 '17 at 09:31
  • @degath Do you mean `java.lang.NoClassDefFoundError: org/hibernate/boot/registry/classloading/internal/ClassLoaderServiceImpl$Work` ? Please post complete stack trace. – ThomasEdwin Dec 15 '17 at 12:21
  • 1
    @degath make sure you're using all the same versions of the Hibernate artifacts. You cannot mix versions. – Naros Dec 15 '17 at 13:34
  • @degath this might help https://stackoverflow.com/questions/26391559/error-creating-bean-with-name-entitymanagerfactory-invocation-of-init-method-f as pointed out by Naros – ThomasEdwin Dec 16 '17 at 02:23
  • "You need to add @Audited to all related entities.", but in my example there are no related entities. – degath Dec 18 '17 at 07:08