java之Hibernate Envers 不使用 SpringMVC 配置在审计表中写入任何内容
当我保存、更新或删除数据库中的条目时,我正在尝试使用 Enverse 来审核表。
Envers 配置如下:
pom.xml
<!-- Spring -->
<org.springframework-version>4.1.6.RELEASE</org.springframework-version>
<!-- Hibernate -->
<hibernate.version>4.3.5.Final</hibernate.version>
[...]
<!-- Hibernate -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>${hibernate.version}</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-envers</artifactId>
<version>${hibernate.version}</version>
</dependency>
我的jpa-tx-config.xml
<bean id="emf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
</property>
<property name="packagesToScan" value="my.domain"/>
<property name="persistenceUnitName" value="persistenceUnit"/>
<property name="jpaProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</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>
<prop key="hibernate.max_fetch_depth">3</prop>
<prop key="hibernate.jdbc.fetch_size">50</prop>
<prop key="hibernate.jdbc.batch_size">20</prop>
<prop key="hibernate.show_sql">false</prop>
<prop key="hibernate.format_sql">true</prop>
<prop key="org.hibernate.envers.audit_table_suffix">_H</prop>
<prop key="org.hibernate.envers.revision_field_name">AUDIT_REVISION</prop>
<prop key="org.hibernate.envers.revision_type_field_name">ACTION_TYPE</prop>
<prop key="org.hibernate.envers.audit_strategy">org.hibernate.envers.strategy.ValidityAuditStrategy</prop>
<prop key="org.hibernate.envers.audit_strategy_validity_end_rev_field_name">AUDIT_REVISION_END</prop>
<prop key="org.hibernate.envers.audit_strategy_validity_store_revend_timestamp">True</prop>
<prop key="org.hibernate.envers.audit_strategy_validity_revend_timestamp_field_name">AUDIT_REVISION_END_TS</prop>
<prop key="jadira.usertype.databaseZone">jvm</prop>
</props>
</property>
</bean>
我的每个域类都有 @Audited
注释,但在 DB 中,此字段永远为 null
。
我不明白哪里出了问题,有什么建议吗?
编辑
作为对评论的回应:每个实体类都扩展了一个实现可审核方式的抽象域。按照代码:
@SuppressWarnings("serial")
@MappedSuperclass
@Audited
public abstract class AbstractDomain implements Auditable<String, Long>, Serializable {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private Long id;
@Version
private int version;
@JsonIgnore
@Column(updatable=false)
private String createdBy;
@Type(type="org.jadira.usertype.dateandtime.joda.PersistentDateTime")
@DateTimeFormat(iso=ISO.DATE_TIME)
@JsonIgnore
@Column(updatable=false)
private DateTime createdDate;
@JsonIgnore
private String lastModifiedBy;
@Type(type="org.jadira.usertype.dateandtime.joda.PersistentDateTime")
@DateTimeFormat(iso=ISO.DATE_TIME)
@JsonIgnore
private DateTime lastModifiedDate;
唯一修改的字段是版本,其他字段被忽略。
请您参考如下方法:
据我所见,您实际上不需要 envers
根本。 Envers 更多关于存储 revisions
您的数据(当然可以用于审计目的)但是如果您只想拥有这些 createdBy
, createdDate
, lastModifiedBy
, lastModifiedDate
字段有一个更简单的方法。
因为您已经在使用 spring-data-jpa
我建议你启用 JPA auditing
与 @EnableJpaAuditing
注释。
然后你可以放下@Audited
来自你的 AbstractDomain
类并添加 @EntityListeners(AuditingEntityListener.class)
这将强制 Hibernate 每次在实体持久化时保存审计信息。
最后但并非最不重要的事情是定义 AuditorAware
bean 。它将告诉每个时刻究竟是谁在操纵给定的实体,因此审计监听器将知道应将哪些数据设置为 createdBy
和 lastModifiedBy
领域。 很简单,举个例子:
@Bean
AuditorAware auditor() {
// return () -> "system"; // Fixed principal
// and for spring-security
return () -> {
Authentication authentication = SecurityContextHolder.getContext()
.getAuthentication();
if (authentication == null || !authentication.isAuthenticated()) {
return null;
}
return authentication.getPrincipal().toString();
}
}
就是这样。
这是一个完整的例子:
@SpringBootApplication
@EnableJpaAuditing
public class So45347635Application {
public static void main(String[] args) { SpringApplication.run(So45347635Application.class, args); }
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public static abstract class AbstractDomain extends AbstractPersistable<Long> implements Auditable<String, Long> {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Version
private int version;
@Column(updatable = false)
private String createdBy;
@Temporal(TemporalType.TIMESTAMP)
@Column(updatable = false)
private Date createdDate;
private String lastModifiedBy;
@Temporal(TemporalType.TIMESTAMP)
@Column(insertable = false)
private Date lastModifiedDate;
@Override
public String getCreatedBy() {
return this.createdBy;
}
@Override
public void setCreatedBy(String createdBy) {
this.createdBy = createdBy;
}
@Override
public DateTime getCreatedDate() {
return null == this.createdDate ? null : new DateTime(this.createdDate);
}
@Override
public void setCreatedDate(DateTime createdDate) {
this.createdDate = createdDate.toDate();
}
@Override
public String getLastModifiedBy() {
return this.lastModifiedBy;
}
@Override
public void setLastModifiedBy(String lastModifiedBy) {
this.lastModifiedBy = lastModifiedBy;
}
@Override
public DateTime getLastModifiedDate() {
return null == this.lastModifiedDate ? null : new DateTime(this.lastModifiedDate);
}
@Override
public void setLastModifiedDate(DateTime lastModifiedDate) {
this.lastModifiedDate = lastModifiedDate.toDate();
}
}
@Entity
@Table(name = "users")
public static class User extends AbstractDomain {
private String username = "anonymous";
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
@Override
public String toString() {
return String.format("User{id=%d, createdBy='%s', createdDate=%s, lastModifiedBy='%s', lastModifiedDate=%s, username='%s'}",
getId(), getCreatedBy(), getCreatedDate(), getLastModifiedBy(), getLastModifiedDate(), username);
}
}
@Bean
AuditorAware auditor() { return () -> "system"; }
@Bean
CommandLineRunner start(UserRepository userRepository, TransactionTemplate tx) {
return args -> tx.execute(ctx -> {
final User user = userRepository.save(new User());
user.setUsername("admin");
System.out.println(">>>> " + userRepository.save(user));
return null;
});
}
}
interface UserRepository extends CrudRepository<So45347635Application.User, Long> {
}
输出:
create table users (id bigint generated by default as identity, created_by varchar(255), created_date timestamp, last_modified_by varchar(255), last_modified_date timestamp, version integer not null, username varchar(255), primary key (id));
insert into users (id, created_by, created_date, last_modified_by, version, username) values (null, 'system', '28-Jul-17', 'system', 0, 'anonymous');
update users set last_modified_by='system', last_modified_date='28-Jul-17', version=1, username='admin' where id=1 and version=0;
1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。