使用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接口和自定义实体操作监听器,可以在创建或修改数据时自动为审计信息赋值,减少了冗长的手动赋值代码,如有错误,还望批评指正。

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

相关推荐
菜鸟‍5 小时前
【后端项目】苍穹外卖day01-开发环境搭建
java·开发语言·spring boot
indexsunny6 小时前
互联网大厂Java求职面试实战:核心技术与业务场景解析
java·spring boot·redis·微服务·kafka·互联网大厂·面试技巧
程序猿大波6 小时前
基于java,SpringBoot和Vue餐饮公司食堂管理系统设计
java·vue.js·spring boot
wuyaolong0077 小时前
Spring Boot 3.4 正式发布,结构化日志!
java·spring boot·后端
a5629916198 小时前
【springboot】Spring 官方抛弃了 Java 8!新idea如何创建java8项目
java·spring boot·spring
编程小风筝10 小时前
如何用redission实现springboot的分布式锁?
spring boot·分布式·后端
码喽7号11 小时前
Springboot学习六:MybatisPlus的多表查询以及分页查询
java·spring boot·学习
不吃香菜学java11 小时前
苍穹外卖-新增菜品需求分析
java·spring boot·spring·tomcat·maven·ssm
智能工业品检测-奇妙智能13 小时前
开源知识库平台有哪些
服务器·人工智能·spring boot·开源·openclaw·奇妙智能
计算机学姐13 小时前
基于SpringBoot的中药材店铺管理系统
java·vue.js·spring boot·后端·spring·tomcat·推荐算法