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

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

相关推荐
seventeennnnn1 小时前
谢飞机的Java高级开发面试:从Spring Boot到分布式架构的蜕变之旅
spring boot·微服务架构·java面试·分布式系统·电商支付
超级小忍2 小时前
服务端向客户端主动推送数据的几种方法(Spring Boot 环境)
java·spring boot·后端
时间会给答案scidag3 小时前
报错 400 和405解决方案
vue.js·spring boot
Wyc724093 小时前
SpringBoot
java·spring boot·spring
ladymorgana5 小时前
【Spring Boot】HikariCP 连接池 YAML 配置详解
spring boot·后端·mysql·连接池·hikaricp
GJCTYU7 小时前
spring中@Transactional注解和事务的实战理解附代码
数据库·spring boot·后端·spring·oracle·mybatis
风象南8 小时前
SpringBoot敏感配置项加密与解密实战
java·spring boot·后端
写不出来就跑路9 小时前
暑期实习感悟与经验分享:从校园到职场的成长之路
java·开发语言·经验分享·spring boot
程序员张313 小时前
Maven编译和打包插件
java·spring boot·maven
灵犀学长14 小时前
EasyExcel之SheetWriteHandler:解锁Excel写入的高阶玩法
spring boot·excel