使用Spring Data JPA实现审计功能,记录创建人、创建时间、最后修改时间和最后修改人

@[toc]

前言

近日心血来潮想做一个开源项目,目标是做一款可以适配多端、功能完备的模板工程,包含后台管理系统和前台系统,开发者基于此项目进行裁剪和扩展来完成自己的功能开发。

本项目为前后端分离开发,后端基于Java21SpringBoot3开发,后端使用Spring SecurityJWTSpring Data JPA等技术栈,前端提供了vueangularreactuniapp微信小程序等多种脚手架工程。

在项目中每条数据在创建或修改的时候,我想记录创建人,创建时间,最后修改人,最后修改时间等审计信息。如果每次都手动赋值,代码会变得冗长,显得很不优雅。Spring Data JPA为我们提供了审计功能,可以在执行创建或修改操作时自动为审计信息赋值。

本文将介绍两种实现方式,关于SpringBoot项目如何整合Spring Data JPA,请参阅blog.csdn.net/kingslave1/...

实现方式

使用Spring Data JPA实现审计功能,主要涉及以下注解:

  • @EnableJpaAuditing,启用JPA审计功能开关。
  • @EntityListeners,可以监听实体对象的增删改查操作,调用监听器中设置的回调方法。
  • @CreatedBy,创建人,执行insert操作时自动赋值。
  • @CreatedDate,创建日期,执行insert操作时自动赋值。
  • @LastModifiedBy,最后修改人,执行insertupdate操作时自动赋值。
  • @LastModifiedDate,最后修改时间,执行insertupdate操作时自动赋值。

基于AuditorAware接口实现审计功能

启用JPA审计功能

定义一个配置类Bean,启用Spring Data JPA和审计功能,也可以直接main方法所在类上直接添加@EnableJpaRepositories@EntityScan@EnableJpaAuditing注解。

java 复制代码
/**
 * Spring Data JPA Bean配置
 * 启用Jpa,扫描指定包下的Repository类和指定包下的实体类
 */
@Configuration
@EnableJpaRepositories(basePackages = {"com.demo.data.repo"})
@EntityScan(basePackages = "com.demo.data.model")
@EnableJpaAuditing
public class JpaConfig {
}

定义实体类

以定义一个用户类SysUser为例,为其添加@EntityListeners({AuditingEntityListener.class})注解,在其审计信息属性上添加@CreatedBy等注解。

java 复制代码
@Getter
@Setter
@Entity
@EntityListeners({AuditingEntityListener.class})
public class SysUser implements Serializable {
    /**
     * ID,唯一标识列,使用主键自增策略
     */
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    /**
     * 创建时间
     */
    @CreatedDate
    private LocalDateTime createdTime;
    /**
     * 最后修改时间
     */
    @LastModifiedDate
    private LocalDateTime lastModifiedTime;
    /**
     * 创建人ID
     */
    @CreatedBy
  	private Long creatorId;
    /**
     * 最后修改人ID
     */
    @LastModifiedBy
    private Long lastModifierId;    
    /**
     * 用户名
     */
    @Column(unique = true)
    private String username;
    /**
     * 密码
     */
    private String password;
    /**
     * 电话
     */
    private String phone;
}

实现AuditorAware接口

我们需要定义一个AuditorAware接口的实现类,并将其注册为Bean。

实现AuditorAware<T>接口需要传递类型参数,这个参数应使用创建人(creatorId)最后修改人(lastModifierId)属性的类型,在实体类SysUsercreatorIdlastModifierId的类型是Long,则此处泛型参数也应该为Long

java 复制代码
@Component
public class AuditorAwareImpl implements AuditorAware<Long> {
    /**
     * 返回当前用户ID,insert和update操作会调用该方法自动赋值
     */
    @Override
    public Optional<Long> getCurrentAuditor() {
        // 获取当前用户Id,具体获取逻辑请自行实现
        Long userId = 1L;
        return Optional.ofNullable(userId);
    }
}

至此,审计功能开发完成,可调用SysUser类的Repository接口执行创建或修改操作来测试是否开发成功。

基于自定义监听器实现审计功能

基于AuditorAware接口实现审计功能虽然简单,但也存在不适用的场景,例如创建人属性不仅要记录创建人的用户ID,还需要记录创建人的用户名时;或者开发者希望仅在insert操作时执行某些操作。 针对上述场景,可以考虑使用自定义实体操作监听器的方式实现,实现步骤如下。

启用JPA审计功能

定义一个配置类Bean,启用Spring Data JPA和审计功能,也可以直接main方法所在类上直接添加@EnableJpaRepositories@EntityScan@EnableJpaAuditing注解。

java 复制代码
/**
 * Spring Data JPA Bean配置
 * 启用Jpa,扫描指定包下的Repository类和指定包下的实体类
 */
@Configuration
@EnableJpaRepositories(basePackages = {"com.demo.data.repo"})
@EntityScan(basePackages = "com.demo.data.model")
@EnableJpaAuditing
public class JpaConfig {
}

定义实体类

以定义一个用户类SysUser为例,为其添加@EntityListeners({AuditingEntityListener.class, CustomEntityAuditingListener.class})注解,在其审计信息属性上添加@CreatedBy等注解。 与1.2一节中给出的实体类相比,新增了creatorlastModifier两个属性,@EntityListeners注解中多了一个CustomEntityAuditingListener,在下一节中笔者将给出CustomEntityAuditingListener的实现代码。

java 复制代码
@Getter
@Setter
@Entity
@EntityListeners({AuditingEntityListener.class, CustomEntityAuditingListener.class})
public class SysUser implements Serializable {
    /**
     * ID,唯一标识列,使用主键自增策略
     */
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    /**
     * 创建时间
     */
    @CreatedDate
    private LocalDateTime createdTime;
    /**
     * 最后修改时间
     */
    @LastModifiedDate
    private LocalDateTime lastModifiedTime;
    /**
     * 创建人ID
     */
    @CreatedBy
  	private Long creatorId;
    /**
     * 创建人用户名
     */
    private String creator;
    /**
     * 最后修改人ID
     */
    @LastModifiedBy
    private Long lastModifierId;  
    /**
     * 最后修改人用户名
     */  
    private Long lastModifier;  
    /**
     * 用户名
     */
    @Column(unique = true)
    private String username;
    /**
     * 密码
     */
    private String password;
    /**
     * 电话
     */
    private String phone;
}

定义自定义监听器类

自定义监听器会用到以下几种注解,可以监听数据库操作的不同时机。

  • @PostLoad,实体对象查询之后
  • @PrePersist,实体对象保存之前
  • @PostPersist,实体对象保存之后
  • @PreUpdate,实体对象修改之前
  • @PostUpdate,实体对象修改之后
  • @PreRemove,实体对象删除之前
  • @PostRemove,实体对象删除之后

以下是CustomEntityAuditingListener类的实现代码,使用了@PrePersist@PreUpdate两个注解。

java 复制代码
public class CustomEntityAuditingListener {
    @PrePersist
    private void prePersist(BaseEntity entity) {
        // 获取当前用户,具体获取逻辑请自行实现
        SysUser current = new SysUser();

        entity.setCreatorId(current.getId());
        entity.setCreator(current.getUsername());
        entity.setLastModifierId(current.getId());
        entity.setLastModifier(current.getUsername());
    }

    @PreUpdate
    private void preUpdate(BaseEntity entity) {
        // 获取当前用户,具体获取逻辑请自行实现
        SysUser current = new SysUser();

        entity.setLastModifierId(current.getId());
        entity.setLastModifier(current.getUsername());
    }
}

至此,审计功能开发完成,可调用SysUser类的Repository接口执行创建或修改操作来测试是否开发成功。

总结

本文介绍了两种使用Spring Data JPA实现审计功能的方法,实现AuditorAware接口和自定义实体操作监听器,可以在创建或修改数据时自动为审计信息赋值,减少了冗长的手动赋值代码,如有错误,还望批评指正。

在后续实践中我也是及时更新自己的学习心得和经验总结,希望与诸位看官一起进步。

相关推荐
aq553560022 分钟前
SpringBoot有几种获取Request对象的方法
java·spring boot·后端
steel80881 小时前
Spring Boot 整合 log4j2 日志配置教程
spring boot·单元测试·log4j
lierenvip1 小时前
Spring Boot中Tomcat配置
spring boot·tomcat·firefox
Detachym1 小时前
InsightFlow 服务配置优化与部署实践
java·spring boot·tomcat·maven·状态模式·jar
rainchestnut1 小时前
Spring AI 初步集成(1)-初始化
spring boot
流水武qin1 小时前
SpringAI多模态的基本使用
java·spring boot·spring·ai
小飞Coding1 小时前
Spring 容器生命周期:10大核心扩展接口+实战代码
spring boot
吾诺2 小时前
Spring Boot--@PathVariable、@RequestParam、@RequestBody
java·spring boot·后端
jiankeljx2 小时前
Spring Boot实现多数据源连接和切换
spring boot·后端·oracle
xyyaihxl3 小时前
springboot与springcloud对应版本
java·spring boot·spring cloud