我想让Spring数据审计在我的Spring 3.2.8/Spring Data 1.5/Hibernate 4项目中工作。
根据Spring数据审计文档,我已经将@CreatedBy
等注释添加到我的实体中,由AuditorAware
实现创建,并在JavaConfig中实例化它。然而,它似乎从来没有开火。
我发现文档有点混乱。看起来JavaConfig条目取代了xml条目,但我不确定。
我目前没有任何orm.xml
文件在我的应用程序。说实话,我甚至不确定在哪里/如何配置它,或者我为什么需要它。我所有的实体都在使用注解。我已经尝试添加@EntityListeners(AuditingEntityListener.class)到实体,但这没有帮助。
我当前的实体管理器没有定义persistence.xml文件:
<!-- entity manager -->
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="jpaVendorAdapter" ref="hibernateJpaVendorAdapter"/>
<property name="packagesToScan" value="com.ia.domain"/>
<property name="jpaProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</prop>
<prop key="hibernate.query.substitutions">true '1', false '0'</prop>
<prop key="hibernate.generate_statistics">true</prop>
<prop key="hibernate.show_sql">false</prop>
<prop key="hibernate.format_sql">true</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
<prop key="hibernate.ejb.naming_strategy">org.hibernate.cfg.ImprovedNamingStrategy</prop>
<prop key="hibernate.connection.charSet">UTF-8</prop>
</props>
</property>
</bean>
JavaConfig:
@Configuration
@EnableJpaAuditing
public class AuditConfig {
@Bean
public AuditorAware<User> auditorProvider(){
return new SpringSecurityAuditorAware();
}
}
实体:@EntityListeners({AuditingEntityListener.class})
@Entity
public class User
{
@TableGenerator(name="UUIDGenerator", pkColumnValue="user_id", table="uuid_generator", allocationSize=1)
@Id
@GeneratedValue(strategy=GenerationType.TABLE, generator="UUIDGenerator")
@Column(name="id")
private Long id;
@NotNull
private String username;
@CreatedDate
@NotNull
@Temporal(TemporalType.TIMESTAMP)
@Column(name="created_date", nullable=false)
private Date createdDate;
@LastModifiedDate
@NotNull
@Temporal(TemporalType.TIMESTAMP)
@Column(name="last_modified_date", nullable=false)
private Date lastModifiedDate;
@CreatedBy
@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name="created_by")
private User createdBy;
@LastModifiedBy
@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name="last_modified_by")
private User lastModifiedBy;
private String password;
private Boolean enabled;
...
}
我在我的SpringSecurityAuditorAware
类中放置了一个断点,但它从未被击中。
我还需要一个orm.xml文件吗?这是如何/在哪里从EntityManager引用?
简写:No
在JPA 2.0中,没有XML文件(orm.xml
)就不可能定义这样的实体侦听器。
:
默认实体侦听器—应用于持久性单元中所有实体的实体侦听器—可以通过XML描述符指定。( p.93
长版本:解决方法…
如果项目中的所有实体都扩展了AbstractAuditable
超类,那么您可以将@EntityListeners({AuditingEntityListener.class})
放在AbstractAuditable
上。附加到实体类上的侦听器由其子类继承。
:
继承层次中的多个实体类和映射的超类可以定义侦听器类和/或生命周期回调方法直接在类上。( p.93
注意,子类可以使用@ExcludeSuperclassListeners
注释显式地排除继承的侦听器。
我想引用规范中最后一个有趣的脚注:
JPA 2.0:
被排除的监听器可以通过列表在实体类中重新引入在EntityListeners注释或XML中显式地显示它们entity-listeners元素。(Footnote [45] p.97)
下面是一些代码来说明解决方法:
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 {
}
我认为可以使用Auditable
接口(@EntityListeners
可以出现在接口上)而不是AbstractAuditable
类,但我没有尝试…
参考:JSR-000317 Java Persistence 2.0 - Final Release
使用Stephan的答案https://stackoverflow.com/a/26240077/715640,
我使用自定义侦听器来实现此工作。
@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());
}
}
然后在基类中引用它:
@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;
}
}
在1.9的spring数据中,您可以通过几个注释启用JPA审计。
从文档- http://docs.spring.io/spring-data/jpa/docs/1.9.4.RELEASE/reference/html/#jpa.auditing
使用@EntityListeners(AuditingEntityListener.class)
注释来启用逐个类的审计。我在基类中使用它。
您还需要@EnableJpaAuditing
在@Configuration
类上启用审计。