基于Spring Data的AuditorAware审计功能的示例代码

下面我将详细讲解如何实现基于Spring Data的AuditorAware审计功能,并提供两个示例代码。

什么是AuditorAware?

AuditorAware 是 Spring Data JPA 开始支持的一个新的特性,它可以用于在执行 CRUD 操作时自动更新实体中的 Auditor 相关信息(比如 create_by, last_modified_by 等)。AuditorAware 接口的实现类可以返回一个当前要使用的 Auditor,而 Auditor 则可以是任意对象,比如实体、登录用户等等。

第一个示例

首先,我们需要在 pom.xml 中添加 Spring Data JPA 和 Spring Boot Web 依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

接着,我们需要创建一个实体类 User,这个实体类包含 id、name、createdBy 和 updatedBy 四个字段,并使用 @EntityListeners 注解标注,用来指定使用 JpaAuditingEntityListener 进行实体审计。

@Entity
@EntityListeners(AuditingEntityListener.class)
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(nullable = false)
    private String name;

    @Column(name = "created_by")
    @CreatedBy
    private String createdBy;

    @Column(name = "updated_by")
    @LastModifiedBy
    private String updatedBy;

    // setter 和 getter 省略
}

然后,我们需要添加一个 AuditorAware 实现类,这个实现类需要实现 getCurrentAuditor() 方法,该方法返回一个 Optional 类型的 Auditor 对象。

@Component
public class UserAuditorAware implements AuditorAware<String> {

    @Override
    public Optional<String> getCurrentAuditor() {
        // 获取当前登录用户
        String currentUser = SecurityContextHolder.getContext().getAuthentication().getName();
        return Optional.ofNullable(currentUser);
    }
}

注意,这个实现类需要使用 @Component 注解进行标注,让 Spring Boot 自动扫描并注入到容器中。

最后,我们需要在启动类上添加 @EnableJpaAuditing 注解,启用 JPA 审计功能。

@SpringBootApplication
@EnableJpaAuditing(auditorAwareRef = "userAuditorAware")
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

启动程序,在数据库中创建 user 表,执行 insert 操作,然后查看数据库中的数据,可以看到 createdBy 和 updatedBy 字段都被填充上了当前登录用户。

第二个示例

现在我们来看一个更复杂的示例。假设我们有两个实体类 Book 和 Author,它们之间是一对多的关系。我们需要在操作 Book 的同时,自动更新 Author 中对应字段的值。

首先,我们来创建 Author 实体类,包含 id、name、updatedBy 字段。

@Entity
public class Author {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(nullable = false)
    private String name;

    @Column(name = "updated_by")
    @LastModifiedBy
    private String updatedBy;

    // getter 和 setter 省略
}

接着,我们创建 Book 实体类,包含 id、name 和 author_id 三个字段。在该实体类中使用 @ManyToOne 注解来建立 Book 和 Author 之间的关联关系,并使用 @EntityListeners 注解指定使用 AuditingEntityListener 进行实体审计。

@Entity
@EntityListeners(AuditingEntityListener.class)
public class Book {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(nullable = false)
    private String name;

    @ManyToOne
    @JoinColumn(name = "author_id")
    private Author author;

    // getter 和 setter 省略
}

然后,我们需要添加一个 AuditorAware 实现类 AuthorAuditorAware,它负责在更新 Book 时自动更新 Author 的 updatedBy 字段。

@Component
public class AuthorAuditorAware implements AuditorAware<String> {

    @Autowired
    private EntityManager entityManager;

    @Override
    public Optional<String> getCurrentAuditor() {
        // 获取当前登录用户
        String currentUser = SecurityContextHolder.getContext().getAuthentication().getName();

        // 获取 JPA 审计器
        JpaMetamodelEntityInformation<Book, ?> bookEntityInformation =
                (JpaMetamodelEntityInformation<Book, ?>) JpaEntityInformationSupport.getEntityInformation(Book.class, entityManager);
        JpaEntityInformation<Author, ?> authorEntityInformation =
                JpaEntityInformationSupport.getEntityInformation(Author.class, entityManager);
        JpaEntityInformation<Object, Serializable> entityInformation =
                (JpaEntityInformation<Object, Serializable>) authorEntityInformation.getMetadata()
                        .getDeclaredAssociationMappings().stream()
                        .filter(mappings -> mappings.getOwnerEntityClass().equals(bookEntityInformation.getJavaType())
                                && mappings.getMappedBy().equals("author"))
                        .findFirst()
                        .orElseThrow(() -> new IllegalStateException("Audited property not found."));

        // 获取当前操作的 Book 实例
        Book book = null;
        Object[] states = entityManager.getEntityManagerFactory()
                .getPersistenceUnitUtil()
                .getIdentifier(bookEntityInformation.getEntity(new Book()), null);
        if (states != null) {
            Serializable bookId = (Serializable) states[0];
            book = entityManager.find(Book.class, bookId);
        }

        // 更新 Author 的 updatedBy 字段
        if (book != null) {
            Author author = book.getAuthor();
            if (author != null && authorEntityInformation.hasCompositeId()) {
                entityInformation.getId(author);
                author.setUpdatedBy(currentUser);
            } else if (author != null) {
                author.setUpdatedBy(currentUser);
            }
            return Optional.ofNullable(currentUser);
        }

        return Optional.empty();
    }
}

注意,这个实现类需要使用 @Component 注解进行标注,让 Spring Boot 自动扫描并注入到容器中。

最后,我们需要在启动类上指定 auditorAwareRef,即使用 AuthorAuditorAware 进行审计:

@SpringBootApplication
@EnableJpaAuditing(auditorAwareRef = "authorAuditorAware")
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

启动程序,在数据库中创建 author 和 book 表,执行 insert 操作,然后查看数据库中的数据,可以看到 Author 中的 updatedBy 字段已经被自动更新。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:基于Spring Data的AuditorAware审计功能的示例代码 - Python技术站

(0)
上一篇 2023年5月20日
下一篇 2023年5月20日

相关文章

  • ajax动态赋值echarts的实例(饼图和柱形图)

    我将详细讲解“ajax动态赋值echarts的实例(饼图和柱形图)”的完整攻略。以下是具体步骤: 准备工作 在HTML文件中引入ECharts的JS文件和相应的主题文件 <!– 引入ECharts插件的JS库 –> <script src="https://cdn.bootcdn.net/ajax/libs/echarts/4…

    Java 2023年6月15日
    00
  • SpringBoot2.x配置HTTPS访问的过程

    下面是“SpringBoot2.x配置HTTPS访问的过程”的完整攻略。 1. 生成证书 首先需要生成一对密钥(证书和私钥),可以使用 keytool 工具来生成。在终端中执行以下命令: keytool -genkeypair -alias mycertalias -keyalg RSA -keysize 2048 -storetype PKCS12 -ke…

    Java 2023年5月19日
    00
  • 基于springboot2集成jpa,创建dao的案例

    基于Spring Boot 2集成JPA(Java Persistence API),创建DAO (Data Access Object) 的攻略还是比较简单的。下面我将为你提供一个详细的过程。 1. 创建Spring Boot项目和配置文件 首先,我们需要创建一个Spring Boot的项目,如果你已经创建了一个项目,那就不需要再做这一步了。我们使用Mav…

    Java 2023年5月19日
    00
  • java.lang.ArrayStoreException异常的解决方案

    针对“java.lang.ArrayStoreException异常的解决方案”,我为您提供以下完整攻略: 1. 异常分析 首先,我们需要对“java.lang.ArrayStoreException”进行分析,它是Java语言中的一个异常类型,表示试图将数组中的元素存储到与数组中声明类型不兼容的位置上。比如下面这种代码就会抛出该异常: Object[] o…

    Java 2023年5月27日
    00
  • java实现简单的图书管理系统

    下面就为您详细讲解如何使用Java实现简单的图书管理系统。 1. 软件需求分析 在开发图书管理系统前,首先要进行需求分析。需求分析包括以下内容: 明确系统用户:管理员和读者; 明确系统功能:管理员可以添加、删除、修改图书信息,读者可以查询图书信息; 系统安全性:需要保证管理员权限较高,读者只能进行查询操作。 2. 数据库设计 在实现图书管理系统前,需要设计数…

    Java 2023年5月18日
    00
  • Java 中如何使用 stream 流

    使用 stream 流是 Java 中进行集合 operations 和 transformations 的便捷方法。在 Java 8 中,我们可以对集合进行过滤、映射、排序等操作,可以省去繁琐的 for 循环和 if 判断。下面是 Java 中使用 stream 流的攻略: 一、为集合创建 stream 流 在 Java 中使用 stream 流,需要先为…

    Java 2023年5月26日
    00
  • 简单总结Java IO中stream流的使用方法

    下面是“简单总结Java IO中stream流的使用方法”的完整攻略: 1. Java IO中的Stream流 Java IO(Input/Output)是指Java语言中的输入输出流操作,用于读取和写入数据。在Java IO中,输入输出是用Stream(流)的方式进行的。Stream流提供了InputSteam和OutputStream两个抽象类,它们是所…

    Java 2023年5月26日
    00
  • 详解在SpringBoot中@Transactional事物操作和事物无效问题排查

    详解在SpringBoot中@Transactional事物操作和事物无效问题排查 事物被认为是许多企业应用程序的重要组成部分。在SpringBoot中,我们可以使用@Transactional注解来处理事务。但有时候,这个注解可能无法正常工作,导致事物无效。这时我们需要排查问题。下面是详细攻略: 问题排查 无效的事物操作可能是由以下原因引起的: 事物管理器…

    Java 2023年5月20日
    00
合作推广
合作推广
分享本页
返回顶部