springDataJpa入门教程(8)-JPA EnableJpaAuditing 审计功能

springDataJpa入门教程

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方法被调用的时候,时间字段会自动设置并插入数据库,但是CreatedByLastModifiedBy并没有赋值,因为需要实现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,欢迎大家一起交流学习。

上一篇:springDataJpa入门教程(7)-基于springDataJpa投影(Projection)返回自定义实体类对象
下一篇:springDataJpa入门教程(9)-spring jpa实体属性类型转换器AttributeConverter的用法
  • 0
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值