簡體   English   中英

Spring Boot AuditAware - 數據庫未更新

[英]Spring Boot AuditAware - Database not updating

我是 Spring 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

我用調試器檢查了這個,用戶被正確返回

@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);
        }
    }

審計元數據 class

@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
    ...

Controller 撥打

// .save is not overridden
requestRepository.save(request);

結果 SQL on.save()

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()
}

在跑步中看到 Window

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)

失敗的根本原因在於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基礎 class:

@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 ,請注意“擴展 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 { ... }

持久化配置

@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:Bean 'entityManagerFactory' 類型 [org.springframework.orm.jpa.LocalContainerEntityManagerF actoryBean] 沒有資格被所有 BeanPostProcessors 處理(例如:不符合自動代理的條件)

我認為 SecurityExpression 干擾了工作流程。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM