I\'m trying to get Spring Data Auditing to work in my Spring 3.2.8 / Spring Data 1.5 / Hibernate 4 project.
As per the Spring Data Auditing docs, I\'ve added the
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.
As of JPA 2.0, it is not possible to define such entity listener without an XML file (orm.xml
).
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)
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.
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:
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
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.