springDataJpa入门教程
-
springDataJpa入门教程(1)-基于springBoot的基本增删改查
-
springDataJpa入门教程(2)-Specification动态条件查询+排序+分页
-
springDataJpa入门教程(3-1)-基于EntityManager原生sql多表联合查询+动态条件查询+分页
-
springDataJpa入门教程(3-2)-基于EntityManager原生sql多表联合查询+动态条件查询+分页返回自定义实体类对象
-
springDataJpa入门教程(4)-Example单表动态条件查询+分页
-
springDataJpa入门教程(5)-单表动态条件查询+分页
-
springDataJpa入门教程(6)-多表动态条件查询+分页
-
springDataJpa入门教程(7)-基于springDataJpa投影(Projection)返回自定义实体类对象
-
springDataJpa入门教程(8)-JPA EnableJpaAuditing 审计功能
-
springDataJpa入门教程(9)-spring jpa实体属性类型转换器AttributeConverter的用法
-
springDataJpa入门教程(10)-JPA使用过程中遇到的坑及解决方法
springDataJpa入门教程(8)-JPA EnableJpaAuditing 审计功能
在实际的业务系统中,往往需要记录表数据的创建时间、创建人、修改时间、修改人。每次手动记录这些信息比较繁琐,springDataJpa的审计功能可以帮助我们来做这些繁琐的配置,下面来讲一讲springDataJpa的审计功能怎么使用。有需要源码的朋友,请到git上下载源码,源码地址:源码下载地址。java学习交流群:184998348,欢迎大家一起交流学习。
JPA Audit 说明
在spring jpa中,支持在字段或者方法上进行注解@CreatedDate、@CreatedBy、
@LastModifiedDate、@LastModifiedBy,从字面意思可以很清楚的了解,这几个注解的用处。
@CreatedDate
表示该字段为创建时间时间字段,在这个实体被insert的时候,会设置值
@CreatedBy
表示该字段为创建人,在这个实体被insert的时候,会设置值
@LastModifiedDate、@LastModifiedBy同理。
如何使用审计功能
首先申明实体类,需要在类上加上注解@EntityListeners(AuditingEntityListener.class),其次在application启动类中加上注解EnableJpaAuditing,同时在需要的字段上加上@CreatedDate、@CreatedBy、@LastModifiedDate、@LastModifiedBy等注解。
这个时候,在jpa的save方法被调用的时候,时间字段会自动设置并插入数据库,但是CreatedBy和LastModifiedBy并没有赋值,因为需要实现AuditorAware接口来返回你需要插入的值。
1.编写AuditorAware
package com.thizgroup.jpa.study.config;
import java.util.Optional;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.domain.AuditorAware;
@Configuration//使用jpa审计功能,保存数据时自动插入创建人id和更新人id
public class UserAuditorAware implements AuditorAware<Long> {
@Override
public Optional<Long> getCurrentAuditor() {
//从session中获取当前登录用户的id
Long userId = 2L;
return Optional.of(userId);
}
}
2.在实体类中声明@EntityListeners和相应的注解
考虑到所有实体都需要声明,就写在BaseEntity中,其他的实体类通过继承BaseEntity来实现审计功能。
package com.thizgroup.jpa.study.model;
import java.io.Serializable;
import java.util.Date;
import javax.persistence.Column;
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 lombok.Data;
import org.springframework.data.annotation.CreatedBy;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedBy;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
@MappedSuperclass//这个注解的意思是这个类jpa不会为它创建数据库表,
//jpa会将这个类的所有字段映射到它的子类的数据库表中
@Data
@EntityListeners(AuditingEntityListener.class)//对实体属性变化的跟踪,它提供了保存前,保存后,更新前,
// 更新后,删除前,删除后等状态,就像是拦截器一样,你可以在拦截方法里重写你的个性化逻辑。
public abstract class BaseEntity implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
protected Long id;
@CreatedDate//自动填充创建时间
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "create_date",columnDefinition = "timestamp")
protected Date createDate;//创建时间
@LastModifiedDate//自动填充修改时间
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "modify_date",columnDefinition = "timestamp")
protected Date modifyDate;//修改时间
@CreatedBy//自动填充创建人
@Column(name = "created_by",columnDefinition = "bigint")
protected Long createdBy;//创建人
@LastModifiedBy//自动填充修改人
@Column(name = "last_modify_by",columnDefinition = "bigint")
protected Long lastModifyBy;//修改人
}
然后在子类中继承BaseEntity,下面以User类为例,
package com.thizgroup.jpa.study.model;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Table;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Entity
@Table(name = "tb_user")
@Data//使用lombok生成getter、setter
@NoArgsConstructor//生成无参构造方法
public class User extends BaseEntity{
@Column(name = "name",columnDefinition = "varchar(64)")
private String name;
@Column(name = "mobile",columnDefinition = "varchar(64)")
private String mobile;
@Column(name = "email",columnDefinition = "varchar(64)")
private String email;
@Column(name = "age",columnDefinition = "smallint(64)")
private Integer age;
@Column(name = "birthday",columnDefinition = "timestamp")
private Date birthday;
//地址
@Column(name = "address_id",columnDefinition = "bigint(20)")
private Long addressId;
@Builder(toBuilder = true)
public User(Long id,String name, String mobile, String email, Integer age, Date birthday,
Long addressId) {
this.id = id;
this.name = name;
this.mobile = mobile;
this.email = email;
this.age = age;
this.birthday = birthday;
this.addressId = addressId;
}
}
3.在Application 中启用审计@EnableJpaAuditing
package com.thizgroup.jpa.study;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
@SpringBootApplication
//配置springDataJpa扫描Repository的包路径
@EntityScan(basePackages = {"com.thizgroup.jpa.study.model","com.thizgroup.jpa.study.dto"})
@EnableJpaRepositories("com.thizgroup.jpa.study.dao")
@EnableJpaAuditing//启动jpa审计功能
public class JpaApplication {
public static void main(String[] args) {
SpringApplication.run(JpaApplication.class,args);
}
}
注意:经过测试如果你的实体类上面的多个字段使用了@CreatedBy这样的注解,只会有一个生效,也就是说在一次请求中,只会被调用一次。
接下来,写个例子来测试一下,在UserService接口添加一个保存用户的方法,
package com.thizgroup.jpa.study.service;
import com.thizgroup.jpa.study.model.User;
import java.util.List;
/**
* 用户服务
*/
public interface IUserService {
/**
* 添加用户
* @param user
* @return
*/
User addUser(User user);
}
然后在UserServiceImpl实现类实现该方法,
@Override
public User addUser(User user) {
User savedUser = userRepository.save(user);
return savedUser;
}
写个单元测试来验证下jpa审计是否生效,
package com.thizgroup.jpa.study.service;
import com.thizgroup.jpa.study.JpaApplication;
import com.thizgroup.jpa.study.model.User;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.annotation.Rollback;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
@SpringBootTest(classes={JpaApplication.class})
@RunWith(SpringJUnit4ClassRunner.class)
@Transactional(readOnly = false,propagation = Propagation.REQUIRED)
public class UserServiceImplTest {
@Autowired
private IUserService userService;
@Test
@Rollback(value = false)
public void addUserTest(){
User user = User.builder()
.name("李元芳")
.email("yuanfang@qq.com")
.birthday(DateUtils.parse("1998-09-08 12:14:15", "yyyy-MM-dd HH:mm:ss"))
.age(30)
.mobile("18755634343")
.build();
userService.addUser(user);
}
}
运行一下单元测试,结果如下:
好了,至此,springDataJpa功能就介绍完了,有需要源码的朋友,请到git上下载源码,源码地址:https://github.com/hgq0916/springdatajpa-study.git。java学习交流群:184998348,欢迎大家一起交流学习。