Can I use Spring Data JPA Auditing without the orm.xml file (using JavaConfig instead)?

北城余情 提交于 2019-11-29 05:51:10

Short version: No

As of JPA 2.0, it is not possible to define such entity listener without an XML file (orm.xml).

JPA 2.0:

Default entity listeners—entity listeners that apply to all entities in the persistence unit—can be specified by means of the XML descriptor. (p.93)

Long version: The workaround...

If all entities in your project extends an AbstractAuditable superclass then you can put @EntityListeners({AuditingEntityListener.class}) on AbstractAuditable. Listeners attached to an entity class are inherited by its subclasses.

JPA 2.0:

Multiple entity classes and mapped superclasses in an inheritance hierarchy may define listener classes and/or lifecycle callback methods directly on the class. (p.93)

Note that a subclass can exclude explicitly an inherited listener using the @ExcludeSuperclassListeners annotation.

There is one last interesting footnote from the spec I'd like to quote:

JPA 2.0:

Excluded listeners may be reintroduced on an entity class by listing them explicitly in the EntityListeners annotation or XML entity-listeners element. (Footnote [45] p.97)


Here is some code for illustrating the workaround:

AbstractAuditableEntity.java

import java.util.Date;

import javax.persistence.EntityListeners;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.MappedSuperclass;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;

import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;

@MappedSuperclass
@EntityListeners({AuditingEntityListener.class}) // AuditingEntityListener will also audit any subclasses of AbstractAuditable...
public abstract class AbstractAuditableEntity {
    @Id
    @GeneratedValue
    private Long id;

    @CreatedDate
    @Temporal(TemporalType.TIMESTAMP)
    private Date createdDate;

    @LastModifiedDate
    @Temporal(TemporalType.TIMESTAMP)
    private Date lastModifiedDate;
}

MyEntity.java

@Entity
public abstract class MyEntity extends AbstractAuditableEntity {

}

I think an interface Auditable may be used (@EntityListeners can appear on an interface) instead of an AbstractAuditable class but I didn't try...


Reference: JSR-000317 Java Persistence 2.0 - Final Release

Justin Smith

Using Stephan's answer, https://stackoverflow.com/a/26240077/715640,

I got this working using a custom listener.

@Configurable
public class TimestampedEntityAuditListener {

    @PrePersist
    public void touchForCreate(AbstractTimestampedEntity target) {
        Date now = new Date();
        target.setCreated(now);
        target.setUpdated(now);
    }

    @PreUpdate
    public void touchForUpdate(AbstractTimestampedEntity target) {
        target.setUpdated(new Date());
    }
}

And then referencing it in my base class:

@MappedSuperclass
@EntityListeners({TimestampedEntityAuditListener.class})
public abstract class AbstractTimestampedEntity implements Serializable {

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

    @Temporal(TemporalType.TIMESTAMP)
    private Date created;

    @Temporal(TemporalType.TIMESTAMP)
    private Date updated;

    public Date getCreated() {
        return created;
    }

    public void setCreated(Date created) {
        this.created = created;
    }

    public Date getUpdated() {
        return updated;
    }

    public void setUpdated(Date updated) {
        this.updated = updated;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }
}

FWIW, I'm using this in a spring-boot project, without an orm.xml file.

In 1.9 of spring data you can enable JPA audits with a couple annotations.

From the docs - http://docs.spring.io/spring-data/jpa/docs/1.9.4.RELEASE/reference/html/#jpa.auditing

Using the @EntityListeners(AuditingEntityListener.class) annotation to enable class by class audits. I use it in a base class.

You'll also need @EnableJpaAuditing on a @Configuration class to enable audits in general.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!