下面我将详细讲解如何实现基于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技术站