Spring Boot:Spring Data JPA开启审计功能,自动保存操作人操作时间_"implementation \"org.springframework.boot:spring-_晴空排云的博客-程序员宅基地

技术标签: spring  spring boot  java  mysql  SpringBoot  后端  

有些业务数据对数据的创建、最后更新时间以及创建、最后操作人进行记录。如果使用Spring Data Jpa做数据新增或更新,可实现自动保存这些信息而不需要显示设置对应字段的值,可通过以下步骤进行配置。

1 相关注解

实现自动记录上述信息主要有5个注解:

  • @EnableJpaAuditing:审计功能开关
  • @CreatedBy:标记数据创建者属性
  • @LastModifiedBy:标记数据最近一次修改者属性
  • @CreatedDate:标记数据创建日期属性
  • @LastModifiedDate:标记数据最近一次修改日期属性

2 实现过程

2.1 依赖引用

使用Spring Data JPA要引用依赖spring-boot-starter-data-jpa,gradle引用方式如下

implementation 'org.springframework.boot:spring-boot-starter-data-jpa'

2.2 实体类标记审计属性

案例使用User实体演示过程,需要在实体对应的字段上添加对应的注解表示是审计属性,另外需要在实体类上开启审计监听,如下:

@Entity
@Table(name = "h_user")
@EntityListeners({
    AuditingEntityListener.class})//开启审计监听
public class User {
    
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    //保存创建人的字段
    @CreatedBy
    @Column(name = "created_by")
    private String createdBy;
    //保存最近修改人的字段
    @LastModifiedBy
    @Column(name = "last_modified_by")
    private String lastModifiedBy;
    //保存创建时间的字段
    @CreatedDate
    @Column(name = "created_date")
    //保存最近修改日期的字段
    private Date createdDate;
    @LastModifiedDate
    @Column(name = "last_modified_date")
    private Date lastModifiedDate;
    private String realName;
    private String username;
    private String mobile;
    private String email;
    private String password;
    private Integer flag;
    
    public Integer getId() {
    
        return id;
    }

    public void setId(Integer id) {
    
        this.id = id;
    }

    public String getCreatedBy() {
    
        return createdBy;
    }

    public void setCreatedBy(String createdBy) {
    
        this.createdBy = createdBy;
    }

    public String getLastModifiedBy() {
    
        return lastModifiedBy;
    }

    public void setLastModifiedBy(String lastModifiedBy) {
    
        this.lastModifiedBy = lastModifiedBy;
    }

    public Date getCreatedDate() {
    
        return createdDate;
    }

    public void setCreatedDate(Date createdDate) {
    
        this.createdDate = createdDate;
    }

    public Date getLastModifiedDate() {
    
        return lastModifiedDate;
    }

    public void setLastModifiedDate(Date lastModifiedDate) {
    
        this.lastModifiedDate = lastModifiedDate;
    }
    
    public String getRealName() {
    
        return this.realName;
    }

    public void setRealName(String realName) {
    
        this.realName = realName;
    }

    public String getUsername() {
    
        return username;
    }

    public void setUsername(String username) {
    
        this.username = username;
    }

    public String getMobile() {
    
        return mobile;
    }

    public void setMobile(String mobile) {
    
        this.mobile = mobile;
    }

    public String getEmail() {
    
        return email;
    }

    public void setEmail(String email) {
    
        this.email = email;
    }

    @JsonIgnore
    public String getPassword() {
    
        return password;
    }

    public void setPassword(String password) {
    
        this.password = password;
    }

    public Integer getFlag() {
    
        return flag;
    }

    public void setFlag(Integer flag) {
    
        this.flag = flag;
    }
}

上述User实体对应数据表定义如下:

create table h_user
(
	id int auto_increment primary key,
	username varchar(30) default '' not null comment '登录用户名',
	real_name varchar(30) default '' null comment '真实姓名',
	mobile varchar(25) default '' null comment '手机号码',
	email varchar(30) default '' null comment '邮箱',
	password varchar(100) default '' null comment '加密密码',
	flag int default '0' null comment '用户标记',
	created_by varchar(50) default 'HSystem' null comment '创建人',
	created_date datetime default CURRENT_TIMESTAMP not null,
	last_modified_by varchar(30) default 'HSystem' null comment '修改人',
	last_modified_date datetime default CURRENT_TIMESTAMP not null,
	constraint user_username_uindex unique (username)
)
engine=InnoDB;

2.3 审计自定义操作

当对实体有新增或保存操作时,系统会自动获取操作时的系统时间作为创建时间和修改时间。对于创建者或最后修改这,审计过程会获取当前登录系统的用户信息,当未登录的情况下,需要指定默认操作,可通过实现AuditorAware类来实现。下面代码在未获取到用户信息时返回HSystem表示默认为系统操作。

@Configuration
public class SpringSecurityAuditorAware implements AuditorAware<String> {
    
    final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Override
    public Optional<String> getCurrentAuditor() {
    
        try {
    
            Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
            if (authentication instanceof AnonymousAuthenticationToken) {
    
                return Optional.of("HSystem");
            } else {
    
                if (authentication == null) {
    
                    return Optional.of("HSystem");
                }
                User user = (User) authentication.getPrincipal();
                return Optional.of(user.getUsername());
            }
        } catch (Exception ex) {
    
            logger.error("get user Authentication failed: " + ex.getMessage(), ex);
            return Optional.of("HSystem");
        }
    }
}

2.4 应用开启审计功能

在应用程序入口类添加注解@EnableJpaAuditing开启审计功能,如下

@SpringBootApplication
//启用JPA审计功能,自动填充@CreateDate、@CreatedBy、@LastModifiedDate、@LastModifiedBy注解的字段
@EnableJpaAuditing(auditorAwareRef = "springSecurityAuditorAware")
public class HBackendApplication {
    
    public static void main(String[] args) {
    
        SpringApplication.run(HBackendApplication.class, args);
    }
}

注意:如果系统中有多个审计实现,需要指定Bean的名称,上面案例中使用名称为springSecurityAuditorAware的bean。

2.5 实体操作

定义User实体类的JPA操作接口UserRepository如下

@Repository
public interface UserRepository extends PagingAndSortingRepository<User, Integer>, JpaRepository<User, Integer> {
    
}

例如创建用户时代码如下,不需要显示设置上面提到的4个属性

User user = new User();
user.setUsername(username.trim());
user.setPassword(this.passwordEncoder.encode(password));
user.setEmail("[email protected]");
user.setFlag(0);
user.setMobile("18988888888");
user.setRealName(username);
this.userRepository.save(user);

当使用UserRepositoryUser类进行保存时,系统会自动记录数据的审计属性值。最终效果如下:
在这里插入图片描述

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/lxh_worldpeace/article/details/105582259

智能推荐

《聆听宇宙的歌唱》——超越故乡-程序员宅基地

巴尔扎克认为小说是一个民族的秘史,米兰·昆德拉认为小说是人类精神境界的最高综合,普鲁斯特认为小说是寻找逝去时间的工具——并且物化在文字的海洋。莫言眼中的小说是什么样?1985年,他说小说是梦境和真实的结合;1986年,他说小说是一曲忧邑的、埋葬童年的挽;1987年,他说小说是人类情绪的容器;1988年,小说是人类寻找失落的精神家园的古老的雄心。他的写作,就是寻找失去的故乡。小说三要素——语_《聆听宇宙的歌唱》

android tv 蓝牙服务_Android TV Remote Service-程序员宅基地

Android TV Remote Service详情This is the service that allows use of your Android phone or tablet as a remote for your Android TV. Easily switch between d-pad and touchpad modes to navigate content and p..._android tv remote service

【Java多线程】volatile原理&happens-before规则_volatile和happends--程序员宅基地

1.Java 内存模型中的可见性、原子性和有序性1.1 可见性可见性,是指线程之间的可见性,一个线程修改的状态对另一个线程是可见的。1.2 原子性原子是世界上的最小单位,具有不可分割性。1.3 有序性Java 语言提供了 volatile 和 synchronized 两个关键字来保证线程之间操作的有序性,volatile 是因为其本身包含“禁止指令重排序”的语义,synchronized 是由“一个变量在同一个时刻只允许一条线程对其进行 lock 操作”这条规则获得的,此规则决定了持有同一个对_volatile和happends-

在线演示(动画演示)各种算法的实现过程-程序员宅基地

在王道老师的视频中推荐的网址:https://www.cs.usfca.edu/~galles/visualization/Algorithms.html

SSIS学习(四) - SSIS+CDC 增量抽取数据_ssis增量抽取更新表-程序员宅基地

前三节主要是入门和单独使用,本章重点SSIS结合CDC做数据增量抽取(insert,update,delete)一 在开启表的CDC基础上,建立cdc记录表用于每次增量的记录_ssis增量抽取更新表

JVM —— 移除永久代_jvm去除永久代-程序员宅基地

转载来源:https://blog.csdn.net/wenniuwuren/article/details/51170275最近准备生产环境 JDK 升级到 1.8,本地先升级了下,发现-XX:PermSize 和-XX:MaxPermSize 已经失效,取而代之的是一个新的区域 —— Metaspace(元数据区)。在 JDK 1.7 及以往的 JDK 版本中,Java 类信息、常..._jvm去除永久代

随便推点

<Eclipse 学习笔记> Eclipse 开发常用快捷键-程序员宅基地

Eclipse常用快捷键1几个最重要的快捷键代码助手:Ctrl+Space(简体中文操作系统是Alt+/)快速修正:Ctrl+1单词补全:Alt+/打开外部Java文档:Shift+F2显示搜索对话框:Ctrl+H快速Outline:Ctrl+O打开资源:Ctrl+Shift+R打开类型:Ctrl+Shift+T显示重构菜单:Alt+...

如何从 Python 列表中删除所有出现的元素?_python 遍历列表时删除元素_wljslmz的博客-程序员宅基地

在 Python 中,列表是一种非常常见且强大的数据类型。但有时候,我们需要从一个列表中删除特定元素,尤其是当这个元素出现多次时。本文将介绍如何使用简单而又有效的方法,从 Python 列表中删除所有出现的元素。_python 遍历列表时删除元素

.NET4.0并行计算技术基础(11)_.net 4.0 plinq-程序员宅基地

19.1让查询执行得更快——Parallel LINQ LINQ的出现对于.NET平台而言是一件大事,它使用一种统一的模式查询数据,并且可以紧密地与具体编程语言直接集成。LINQ语句的编写方式是“动态组合”和“递归”的,这与函数式编程语言(如F#)类似,这种编写方式的优点在于代码量小,通过动态_.net 4.0 plinq

画直线-程序员宅基地

import turtlet=turtle.Turtle()w=turtle.Screen()t.forward(100)turtle.done()

caffe了(window官方版win7+VS2013)-程序员宅基地

转自:http://blog.sina.com.cn/s/blog_74f32c400102wjli.html终于搞定caffe了(window官方版win7+VS2013) (2016-11-20 15:22:35)转载▼图文讲解caffe配置(Windows官方版本+win7+VS2013)终于搞定caffe了,但不得不说,过程很烦,很痛苦,在我看来,计算机或计算机专业真得是不要太蠢,没有一个...

推荐文章

热门文章

相关标签