You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot AuditAware配置后数据库审计字段未更新问题求助

Spring Boot JPA审计字段未更新问题排查与解决

我是Spring Boot新手,想要添加审计支持,参考Spring Data JPA官方文档并经过多次尝试后,数据库中的审计字段(created、created_by、last_modified、last_modified_by)始终未更新。

现有代码配置

持久化配置

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories("com.ncc.vrts")
@EnableJpaAuditing(auditorAwareRef = "auditorAware")
public class PersistenceConfiguration {
    @Bean
    AuditorAware<User> auditorAware() {
        return new AuditorAwareImpl();
    }
}

AuditorAwareImpl(调试确认可正确返回User对象)

@Component
public class AuditorAwareImpl implements AuditorAware<User> {
    @Override
    public Optional<User> getCurrentAuditor() {
        return Optional.ofNullable(SecurityContextHolder.getContext())
                .map(SecurityContext::getAuthentication)
                .filter(Authentication::isAuthenticated)
                .map(Authentication::getPrincipal)
                .map(User.class::cast);
    }
}

AuditMetadata类

@Embeddable
public class AuditMetadata  {
    @ManyToOne(fetch = FetchType.LAZY, cascade = {CascadeType.PERSIST})
    @JoinColumn(name = "created_by")
    @CreatedBy
    private User createdBy;
    @Column(name = "created")
    @CreatedDate
    private Timestamp createdDate;
    @LastModifiedBy
    @ManyToOne(fetch = FetchType.LAZY, cascade = {CascadeType.PERSIST})
    @JoinColumn(name = "last_modified_by")
    private User lastModifiedBy;
    @Column(name = "last_modified")
    @LastModifiedDate
    private Timestamp lastModifiedDate;

    // 无setter和getter(添加后问题仍未解决)
}

实体类

@Entity
@Table(name = "trip_request")
@SQLDelete(sql = "UPDATE trip_request SET deleted = true WHERE id=?")
@FilterDef(name = "deletedRequestFilter", parameters = @ParamDef(name = "isDeleted", type = Boolean.class))
@Filter(name = "deletedRequestFilter", condition = "deleted = :isDeleted")
@EntityListeners(AuditingEntityListener.class)
public class Request {
    ...
    @Embedded
    private AuditMetadata auditingMetadata;
    ...
    // 无setter和getter
}

控制器调用

// .save未被重写
requestRepository.save(request);

生成的SQL

Hibernate: select r1_0.id,r1_0.created_by,r1_0.created,r1_0.last_modified_by,r1_0.last_modified,r1_0.deleted,r1_0.expected_return_date_time,r1_0.last_updated,r1_0.note,r1_0.purpose,r1_0.request_date_time,r1_0.request_submitted,r1_0.status,r1_0.status_reviewed,r1_0.status_user_id,r1_0.user_id,r1_0.vehicle_id from trip_request r1_0 where r1_0.id=?
Hibernate: update trip_request set created_by=?, created=?, last_modified_by=?, last_modified=?, deleted=?, expected_return_date_time=?, last_updated=?, note=?, purpose=?, request_date_time=?, request_submitted=?, status=?, status_reviewed=?, status_user_id=?, user_id=?, vehicle_id=? where id=?

数据库查询结果

select * from trip_request where id=8\G;
*************************** 1. row ***************************
                        id: 8
... 除审计字段外其他字段均正常更新
                   created: NULL
             last_modified: NULL
                created_by: NULL
          last_modified_by: NULL

build.gradle配置

plugins {
    id 'java'
    id 'org.springframework.boot' version '3.0.2'
    id 'io.spring.dependency-management' version '1.1.0'
}

group = 'com.ncc'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '17'

repositories {
    mavenCentral()
}

dependencies {
    implementation 'com.okta.spring:okta-spring-boot-starter:3.0.3'
    implementation 'org.springframework.boot:spring-boot-starter-mail'
    implementation 'org.springframework.boot:spring-boot-starter-validation'
    implementation 'org.springframework.boot:spring-boot-starter-web'
    implementation 'org.springframework.boot:spring-boot-starter-security'
    implementation 'nz.net.ultraq.thymeleaf:thymeleaf-layout-dialect:3.2.0'
    implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
    implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
    implementation 'org.thymeleaf.extras:thymeleaf-extras-springsecurity6'
    implementation 'javax.servlet:javax.servlet-api:4.0.1'
    implementation 'io.hypersistence:hypersistence-utils-parent:3.2.0'
    implementation 'io.hypersistence:hypersistence-utils-hibernate-60:3.2.0'
    implementation 'io.openliberty.features:com.ibm.websphere.appserver.securityContext-1.0:23.0.0.2'
    runtimeOnly 'com.mysql:mysql-connector-j'
    developmentOnly 'org.springframework.boot:spring-boot-devtools'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

tasks.named('test') {
    useJUnitPlatform()
}

运行日志

2023-05-30T07:46:53.311-04:00  INFO 15224 --- [  restartedMain] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default'
2023-05-30T07:46:53.316-04:00  INFO 15224 --- [  restartedMain] trationDelegate$BeanPostProcessorChecker : Bean 'entityManagerFactory' of type [org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)

问题排查与解决方案

1. 初始化嵌入式审计字段

嵌入式字段auditingMetadata默认是null,AuditingEntityListener无法对null对象的字段进行赋值。在Request实体中初始化该字段:

@Embedded
private AuditMetadata auditingMetadata = new AuditMetadata();

2. 替换日期类型为Java 8+时间类

Spring Boot 3.x(对应JPA 3.x)对java.time包下的时间类型支持更完善,替换Timestamp为LocalDateTime:

@Embeddable
public class AuditMetadata  {
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "created_by")
    @CreatedBy
    private User createdBy;

    @Column(name = "created")
    @CreatedDate
    private LocalDateTime createdDate;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "last_modified_by")
    @LastModifiedBy
    private User lastModifiedBy;

    @Column(name = "last_modified")
    @LastModifiedDate
    private LocalDateTime lastModifiedDate;

    // JPA需要无参构造器
    public AuditMetadata() {}
}

3. 避免AuditorAware Bean重复注册

AuditorAwareImpl已经通过@Component注册为Bean,无需在PersistenceConfiguration中手动创建,避免冲突:

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories("com.ncc.vrts")
@EnableJpaAuditing(auditorAwareRef = "auditorAwareImpl") // 使用组件默认名称(类名首字母小写)
public class PersistenceConfiguration {
    // 移除auditorAware()方法
}

4. 确保关联User实体已持久化

@CreatedBy和@LastModifiedBy关联的User对象必须是数据库中已存在的实体(拥有有效主键),否则JPA无法插入关联外键值。确认AuditorAwareImpl返回的User是已持久化的实例。

5. 检查事务上下文

确保save操作在事务中执行,Spring Data JPA的save方法默认带事务,但如果控制器方法未被Spring管理或事务失效,可在控制器/Service方法上添加@Transactional注解。


内容的提问来源于stack exchange,提问作者user2182349

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 13:55:02