java Sping Boot AuditAware -数据库未更新

4smxwvx5  于 2023-06-04  发布在  Java
关注(0)|答案(1)|浏览(150)

我是Sping Boot 的新手,希望添加审计支持。我的大部分灵感来自https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#auditing,以及大量的搜索和尝试。

审核列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();
    }
}

AuditAwareImpl

我用调试器检查过了,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;

    // no setters or getters (although I tried with them and it didn't work either)

实体

@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;
    ...
    // no setter or getter
    ...

控制器调用

// .save is not overridden
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
... all fields updated as expected except audit
                   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)
uxhixvfz

uxhixvfz1#

失败的根本原因在SecurityConfiguration,具体是SecurityExpression处理程序。这段代码是有效的:

安全配置

我从使用@EnableMethodSecurity改为使用@EnableWebSecurity

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true, jsr250Enabled = true)
public class SecurityConfiguration {

    @Bean
    public RoleHierarchyImpl roleHierarchy() {
        RoleHierarchyImpl roleHierarchy = new RoleHierarchyImpl();
        roleHierarchy.setHierarchy("""
            ROLE_ADMIN > ROLE_CAMPUS_SAFETY
            ROLE_CAMPUS_SAFETY > ROLE_USER
        """);
        return roleHierarchy;
    }

    @Bean
    public DefaultWebSecurityExpressionHandler expressionHandler() {
        DefaultWebSecurityExpressionHandler expressionHandler = new DefaultWebSecurityExpressionHandler();
        expressionHandler.setRoleHierarchy(roleHierarchy());
        return expressionHandler;
    }

我用审计和版本数据将实体更新为extend一个基类:

@EntityListeners(AuditingEntityListener.class)
@MappedSuperclass
public class BaseEntity  {
    @Version
    @Column(name = "version")
    private Long version;
    @ManyToOne
    @JoinColumn(name = "created_by")
    @CreatedBy
    private User createdBy;
    @Column(name = "created",updatable = false)
    @CreatedDate
    private Timestamp createdDate;
    @LastModifiedBy
    @ManyToOne
    @JoinColumn(name = "last_modified_by")
    private User lastModifiedBy;
    @Column(name = "last_modified")
    @LastModifiedDate
    private Timestamp lastModifiedDate;

    public void setVersion(Long version) {
        this.version = version;
    }

    public Long getVersion() {
        return version;
    }
}

实体

特别是 Request,请注意**'extends BaseEntity'**

@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")
public class Request extends BaseEntity { ... }

PersistenceConfiguration

@Configuration
@EnableJpaRepositories("com.ncc.vms")
@EnableJpaAuditing(auditorAwareRef = "auditorAware")
public class PersistenceConfiguration {

    @Bean
    AuditorAware<User> auditorAware() {
        return new AuditorAwareImpl();
    }
}

我很抱歉没有解释为什么出现问题-但它与这些消息有关:
2023-05-30T07:46:53.316-04:00 INFO 15224 --- [ restartedMain] trationDelegate$BeanPostProcessorChecker:类型为[org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean]的Bean 'entityManagerFactory'不符合由所有BeanPostProcessors处理的条件(例如:不适合自动代理)
我认为SecurityExpression干扰了工作流。

相关问题