Spring Data JPA教程:审计(一)
2016-02-29 17:58
736 查看
提到审计,首先从脑海中蹦出的就是审计日志,记录了实体版本的修改信息。但是实现审计日志是个既耗时又复杂的任务,幸运的是,大部分时候我们都不需要
然而,还是有些经常碰到的问题:
* 实体什么时候被创建和修改?
* 谁创建和修改了这个实体?
Spring Data JPA的审计功能可以帮助我们解决这两个问题,下面我们介绍一下怎样通过Spring Data JPA提供的审计功能记录实体的创建和修改时间
一开始,我们需要先写一个返回当前日期和时间的服务,定义一个
为什么使用接口而不是类实现这个服务呢,原因如下:
我们想创建两个不同的实现类
第一个实现返回当前的日期和时间
第二个实现用于测试,每次返回相同的日期和时间
如果是个产品应用,其他组件也会通过接口进行调用
下面我们看看怎样将我们写的service与Spring Data JPA进行集成
Spring Data JPA使用
步骤如下:
创建一个
添加一个
实现
下一步是对
创建
加上
加上
相应的配置类如下:
然后,将我们的
创建
返回一个
加上
加上
相应的PersistenceContext配置如下:
下面修改实体类,要实现如下需求:
确保creationTime在第一次存储时被设置
确保modificationTime在第一次存储和每次更新时被设置
通过下面步骤就能实现上述目标:
为creationTime字段加上
为modificationTime字段加上
为实体类加上
相应的Todo实体类修改如下:
OK,搞定!
下一章教程将回答最开始提出的第二个问题:谁创建和修改了实体?
项目代码在作者的github上:https://github.com/pkainulainen/spring-data-jpa-examples/tree/master/query-methods
原文连接:http://www.petrikainulainen.net/programming/spring-framework/spring-data-jpa-tutorial-auditing-part-one
然而,还是有些经常碰到的问题:
* 实体什么时候被创建和修改?
* 谁创建和修改了这个实体?
Spring Data JPA的审计功能可以帮助我们解决这两个问题,下面我们介绍一下怎样通过Spring Data JPA提供的审计功能记录实体的创建和修改时间
一开始,我们需要先写一个返回当前日期和时间的服务,定义一个
DateTimeService接口
为什么使用接口而不是类实现这个服务呢,原因如下:
我们想创建两个不同的实现类
第一个实现返回当前的日期和时间
第二个实现用于测试,每次返回相同的日期和时间
如果是个产品应用,其他组件也会通过接口进行调用
DateTimeService接口的声明只有一个方法:
getCurrentDateAndTime(),该方法返回一个
ZonedDateTime对象
DateTimeService接口代码如下:
import java.time.ZonedDateTime; public interface DateTimeService { ZonedDateTime getCurrentDateAndTime(); }
CurrentTimeDateTimeService实现了
DateTimeService接口,
getCurrentDateAndTime()的实现只是简单的返回了当前时间
CurrentTimeDateTimeService实现如下:
import java.time.ZonedDateTime; public class CurrentTimeDateTimeService implements DateTimeService { @Override public ZonedDateTime getCurrentDateAndTime() { return ZonedDateTime.now(); } }
下面我们看看怎样将我们写的service与Spring Data JPA进行集成
Spring Data JPA使用
DateTimeProvider接口获取日期和时间,所以我们只要实现这个接口就可以将我们的service集成到Spring中
步骤如下:
创建一个
AuditingDateTimeProvider类,实现
DateTimeProvider接口
添加一个
DateTimeService类型的字段,通过构造函数注入
实现
getNow()方法,通过
DateTimeService对象获取当前日期和时间,返回一个
GregorianCalendar对象
AuditingDateTimeProvider实现如下:
import org.springframework.data.auditing.DateTimeProvider; import java.util.Calendar; import java.util.GregorianCalendar; public class AuditingDateTimeProvider implements DateTimeProvider { private final DateTimeService dateTimeService; public AuditingDateTimeProvider(DateTimeService dateTimeService) { this.dateTimeService = dateTimeService; } @Override public Calendar getNow() { return GregorianCalendar.from(dateTimeService.getCurrentDateAndTime()); } }
下一步是对
ApplicationContext进行配置,先创建一个
DateTimeService类型的bean,在configuration class(XML configuration file)中声明。通过如下步骤配置bean:
创建
currentTimeDateTimeService()方法返回一个
CurrentTimeDateTimeService对象
加上
@Bean注解
加上
@Profile注解,值设置为
Profiles.APPLICATION,确保应用启动时bean被创建
相应的配置类如下:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; import org.springframework.context.annotation.Profile; @Configuration @ComponentScan("net.petrikainulainen.springdata.jpa") @Import({WebMvcContext.class, PersistenceContext.class}) public class ExampleApplicationContext { @Profile(Profiles.APPLICATION) @Bean DateTimeService currentTimeDateTimeService() { return new CurrentTimeDateTimeService(); } }
然后,将我们的
DateTimeProviderbean配置到Spring Data JPA,通过更改事例程序的持久化层配置来实现:
创建
dateTimeProvider()方法返回一个
DateTimeProvider对象,构造函数传入我们的
DateTimeService对象
返回一个
AuditingAwareDateTimeProvider对象
加上
@Bean注解
加上
@EnableJpaAuditing注解,dataTimeProviderRef的值设置为dateTimeProvider
相应的PersistenceContext配置如下:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.auditing.DateTimeProvider; import org.springframework.data.jpa.repository.config.EnableJpaAuditing; import org.springframework.data.jpa.repository.config.EnableJpaRepositories; import org.springframework.transaction.annotation.EnableTransactionManagement; @Configuration @EnableJpaAuditing(dateTimeProviderRef = "dateTimeProvider") @EnableJpaRepositories(basePackages = { "net.petrikainulainen.springdata.jpa.todo" }) @EnableTransactionManagement class PersistenceContext { @Bean DateTimeProvider dateTimeProvider(DateTimeService dateTimeService) { return new AuditingDateTimeProvider(dateTimeService); } }
下面修改实体类,要实现如下需求:
确保creationTime在第一次存储时被设置
确保modificationTime在第一次存储和每次更新时被设置
通过下面步骤就能实现上述目标:
为creationTime字段加上
@CreatedDate注解
为modificationTime字段加上
@LastModifiedDate注解
为实体类加上
@EntityListeners注解,将值设置为AuditingEntityListener.class
相应的Todo实体类修改如下:
import org.hibernate.annotations.Type; import org.springframework.data.annotation.CreatedDate; import org.springframework.data.annotation.LastModifiedDate; import org.springframework.data.jpa.domain.support.AuditingEntityListener; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.EntityListeners; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Table; import javax.persistence.Version; import java.time.ZonedDateTime; @Entity @EntityListeners(AuditingEntityListener.class) @Table(name = "todos") final class Todo { @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; @Column(name = "creation_time", nullable = false) @Type(type = "org.jadira.usertype.dateandtime.threeten.PersistentZonedDateTime") @CreatedDate private ZonedDateTime creationTime; @Column(name = "description", length = 500) private String description; @Column(name = "modification_time") @Type(type = "org.jadira.usertype.dateandtime.threeten.PersistentZonedDateTime") @LastModifiedDate private ZonedDateTime modificationTime; @Column(name = "title", nullable = false, length = 100) private String title; @Version private long version; }
OK,搞定!
下一章教程将回答最开始提出的第二个问题:谁创建和修改了实体?
项目代码在作者的github上:https://github.com/pkainulainen/spring-data-jpa-examples/tree/master/query-methods
原文连接:http://www.petrikainulainen.net/programming/spring-framework/spring-data-jpa-tutorial-auditing-part-one
相关文章推荐
- Java中字符流的主要操作归纳
- java 文件读取
- springMVC中ajax的实现
- java swing 防抖机制
- Java线程同步简单总结
- Java容器类简单总结
- java中堆和栈的分析
- localhost: Error: JAVA_HOME is not set.
- POJ 1054 Java: The Troublesome Frog
- eclipse创建webservice简单教程
- Java枚举详解
- @Scheduled(cron="") spring定时任务时间设置
- 【慕课笔记】第六章 JAVA中的集合框架(下) 第2节 学生选课——判断Set中课程是否存在
- Java ServletContext 详解
- java.lang.NoClassDefFoundError: Could not initialize class java.awt.Toolkit异常的解决方法
- java中的内部类总结
- java泛型
- java Timer
- 【Dubbo】Dubbo与Zookeeper、SpringMVC整合和使用(负载均衡、容错)
- Struts2的声明式异常处理