目录

    前言

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

    本项目为前后端分离开发,后端基于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注解。

    /**
     * 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等注解。

    @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

    @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注解。

    /**
     * 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的实现代码。

    @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两个注解。

    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());
    }
    
    <span class="hljs-meta">@PreUpdate</span>
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">preUpdate</span><span class="hljs-params">(BaseEntity entity)</span> {
        <span class="hljs-comment">// 获取当前用户,具体获取逻辑请自行实现</span>
        <span class="hljs-type">SysUser</span> <span class="hljs-variable">current</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">SysUser</span>();
    
        entity.setLastModifierId(current.getId());
        entity.setLastModifier(current.getUsername());
    }
    

    }

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

    总结

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

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