首页 > 其他分享 >使用Spring Data JPA实现审计功能,记录创建人、创建时间、最后修改时间和最后修改人

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

时间:2024-01-26 11:45:14浏览次数:33  
标签:审计 JPA Spring private 修改 class

目录

    前言

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

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

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

    标签:审计,JPA,Spring,private,修改,class
    From: https://www.cnblogs.com/breezefaith/p/17976017

    相关文章

    • SpringBoot中集成XXL-JOB分布式任务调度平台,轻量级、低侵入实现定时任务
      场景XXL-JOBhttps://www.xuxueli.com/xxl-jobXXL-JOB是一个分布式任务调度平台,其核心设计目标是开发迅速、学习简单、轻量级、易扩展。特性:1、简单:支持通过Web页面对任务进行CRUD操作,操作简单,一分钟上手;2、动态:支持动态修改任务状态、启动/停止任务,以及终止运行中任务,即时生......
    • SpringBoot整合Redis
      1、pom.xml中引入redis依赖<!--Redis依赖--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency>2、application.yml配置文件中配置Redis连接参数等s......
    • 修改vSphere ESXi中虚拟机的三大件CPUID,硬盘ID,MAC地址
      1、查看硬件信息 wmicdiskdrivegetserialnumber查看磁盘序列号wmicbiosgetserialnumber查询BIOS序列号wmicnicconfiggetmacaddress查询网卡MAC信息wmiccpugetprocessorid查询cpu的IDwmicbeseboardgetserialnumber查询主板序列号 2、修改CPUID......
    • Spring源码导入IDEA记录
      一、首先Spring源码是gradle搭建,gradle会和jdk版本、IDEA产生兼容问题参考【学不完@根本学不完】的文章:SpringBoot版本与Spring、java、maven、gradle版本对应汇总=>由于本地JDK是1.8对应Java8,按照尽可能看新版本查找=>对应表格里面gradle7.x二、gradle安装步骤gradle历......
    • spring MVC框架
      springMVC框架如果你对springMVC框架有一些疑问,那么以下文章或许可以帮助到你为什么要学习springMVC框架因为它非常的好用,可以说提高了你的效率不止一星半点,可以免去写那些之前的重复代码,让你大部分精力都在业务上虽然它简易,但效率却一点也不低,选择SpringMVC吧先让......
    • Matlab-修改标记点间隔Maker,MarkerIndices
      xx=10;maker_idx_1=1:ceil(length(a)/xx):length(a);maker_idx_1(length(maker_idx_1)+1)=length(a);maker_idx_2=1:ceil(length(c)/xx):length(c);maker_idx_2(length(maker_idx_2)+1)=length(c);maker_idx_3=1:ceil(length(e)/xx):length(e);maker_idx_3(length(ma......
    • Spring Cloud 系列:基于Seata 实现 XA模式
      https://seata.io/zh-cn/docs/user/mode/xahttps://seata.io/zh-cn/docs/dev/mode/xa-modeXA规范是X/Open组织定义的分布式事务处理(DTP,DistributedTransactionProcessing)标准,XA规范描述了全局的TM与局部的RM之间的接口,几乎所有主流的数据库都对XA规范提供了支持。XA......
    • 记一次Spring retry的使用
      问题背景调用三方平台接口偶尔会访问不到,导致了逻辑错误具体描述由于工作职责重新划分,我新接手维护了一个项目,这个项目已经开发完成,项目中需要和第三方平台进行对接,主要是我方向对方推送数据但是刚接手没几天,实施同事就反馈过来一个问题,我们推送过去的数据在对方那边显示......
    • Spring Task定时任务
      任务调度任务调度是为了让系统自动完成任务,在约定好的特定时刻去执行任务的过程列如:在电商系统中需要在下午6点自动发送优惠卷订票系统中根据车次不同,不同时间段分批发票实现任务调度方法多线程方式,利用sleepJDK提供的API:列如Timer,ScheduledExecutor列如Quartzspring......
    • SpringBoot 接口数据加解密解说,你的系统真的安全吗?
      xx项目有于安全问题,需要对接口整体进行加密处理,额,摸摸头上飘摇着而稀疏的长发,感觉我爱了。和产品、前端同学对外需求后,梳理了相关技术方案,主要的需求点如下:尽量少改动,不影响之前的业务逻辑;考虑到时间紧迫性,可采用对称性加密方式,服务需要对接安卓、IOS、H5三端,另外考虑到H5端存储密......