programing

개체를 저장할 때 SpringBoot JPA@CreatedDate@LastModifiedDate가 채워지지 않음

topblog 2023. 7. 7. 18:27
반응형

개체를 저장할 때 SpringBoot JPA@CreatedDate@LastModifiedDate가 채워지지 않음

저는 Postgres 데이터베이스를 사용하여 Spring Boot + JPA로 앱을 작성하고 있습니다.사용자 엔티티가 있으며 사용자 레코드가 저장 및/또는 수정될 때 타임스탬프를 가져오려고 합니다.이거 안 돼요.저장 중인 레코드는 createdDate와 lastModifiedDate 모두에 대해 "null"을 가집니다.

코틀린의 모든 관련 코드는 다음과 같습니다.

@Entity
@Table(name = "app_user")
@EntityListeners(AuditingEntityListener::class)
data class User(
        @Id
        @GeneratedValue(strategy = GenerationType.AUTO)
        @Column(name = "id")
        val id: UUID? = null,

        @NotNull
        @Column(unique = true)
        val email: String,
        val name: String,
        private val password: String,

        @CreatedDate
        @Column(name = "created_date", nullable = false, updatable = false)
        var createdDate: LocalDateTime? = null,

        @LastModifiedDate
        @Column(name = "last_modified_date", nullable = false)
        var lastModifiedDate: LocalDateTime? = null
)

날짜 필드를 추가하는 SQL 쿼리는 다음과 같습니다.

ALTER TABLE app_user
ADD COLUMN last_modified_date TIMESTAMP,
ADD COLUMN created_date TIMESTAMP;

구성 수업도 있습니다.

@Configuration
@EnableJpaAuditing(auditorAwareRef = "auditorProvider")
class JpaAuditingConfiguration {

    @Bean
    fun auditorProvider(): AuditorAware<String> {
        return AuditorAware { Optional.of(SecurityContextHolder.getContext().authentication.name) }
    }

}

그리고 나의 시험 수업:

  @Autowired
    private lateinit var userRepository: UserRepository

    val user = User(
            email = "email",
            name = "name",
            password = "password"
    )

    @Test
    fun `it sets the timestamps when a user is created`() {
        userRepository.save(user)
        user.let {
            assertThat(it.createdDate).isNotNull()
            assertThat(it.lastModifiedDate).isNotNull()
        }
    }

업데이트:

문제는 테스트에서만 발생하는 것 같습니다.테스트가 아닌 개발 환경에서 사용자를 만들기 위해 동일한 코드를 실행해도 괜찮을 것 같습니다.

테스트에 추가 구성이 필요합니까?

업데이트 2

또한 엔티티 관리자를 다음과 같이 사용하려고 했습니다.

@Autowired
lateinit var entityManager: TestEntityManager

그런 다음 테스트에서 다음을 수행합니다.

entityManager.persist(user)
entityManager.flush()

그리고 또

entityManager.persistAndFlush(user)

여전히 타임스탬프를 채우고 있지 않습니다.

AuditingEntityListener 메서드는 에서 호출됩니다.@PrePersist그리고.@PreUpdate단계.

즉, 삽입 또는 업데이트 SQL 문이 실행되기 직전에 호출됩니다.

Hibernate 문서에서 JPA 이벤트에 대해 자세히 알아보기: https://docs.jboss.org/hibernate/orm/5.2/userguide/html_single/Hibernate_User_Guide.html#events-jpa-callbacks

단위 테스트

테스트에서 를 사용하는 경우 테스트에서도 감사를 활성화해야 합니다.

@DataJpaTest
@RunWith(SpringRunner.class)
@EnableJpaAuditing
public class EntityListenerTest {

유사한 문제가 있었습니다(Spring Boot 2.2.1 및 JUNit 5).null가치.추가 중@EnableJpaAuditing테스트 클래스가 작동하지 않았습니다.

예(모든 것을 복사하지 않음):

@Getter(AccessLevel.PROTECTED)
@Setter(AccessLevel.PROTECTED)
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public class Auditable<U> {

    @CreatedBy
    @Column(name = "created_by", nullable = false)
    private U createdBy;

    @CreatedDate
    @Column(name = "created", nullable = false)
    private OffsetDateTime created;
}

및 각 클래스:

@Getter
@Setter
@Entity
@Table(name="survey_records")
public class SurveyRecord extends Auditable<String> implements Serializable {

감사를 위한 구성은 다음과 같습니다.

@Configuration
@EnableJpaAuditing(auditorAwareRef = "auditorProvider", dateTimeProviderRef = "auditingDateTimeProvider")
public class JpaAuditingConfiguration {

    @Bean(name = "auditingDateTimeProvider")
    public DateTimeProvider dateTimeProvider() {
        return () -> Optional.of(OffsetDateTime.now());
    }

    @Bean
    public AuditorAware<String> auditorProvider() {

갖기 위해@CreatedBy그리고.@CreatedDate테스트 내부에서만 작업@Import필요했습니다.

@DataJpaTest
@Import(JpaAuditingConfiguration.class)
class SurveyRecordRepositoryTest {

사용된 참조:

저도 비슷한 문제가 있었지만, 제 사건의 이유는@Transactional테스트 클래스의 주석을 제거한 후에는 모든 것이 예상대로 작동합니다.

내가 선호하는 솔루션은 다음의 테스트를 보장하기 위한 다중 주석 집합입니다.@CreatedBy또는@CreatedDate:

@RunWith(SpringRunner.class)
@DataJpaTest
@Import(JPAConfig.class)
@WithMockUser(username = "testuser")
public class MYRepositoryTest {
...
}

내 엔티티는 다음과 같습니다.

@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public class AbstractEntity {

    @CreatedBy
    private String createdBy;

    @CreatedDate
    private Date createdOn;

    @LastModifiedDate
    private Date updatedOn;

    @LastModifiedBy
    private String updatedBy;
}

내 JPA 구성은 다음과 같습니다.

@Configuration
@EnableJpaAuditing(auditorAwareRef = "auditorAware")
public class JPAConfig {

    @Bean
    public AuditorAware<String> auditorAware() {
        return () -> Optional.of(((User)     SecurityContextHolder.getContext().getAuthentication().getPrincipal()).getUsername());
    }
}

JPA 테스트 중에 감사 필드도 생성되었습니다.

assertThat(result.getCreatedBy()).isNotNull().isEqualTo("testuser");
assertThat(result.getCreatedOn()).isNotNull();
assertThat(result.getUpdatedBy()).isNotNull().isEqualTo("testuser");
assertThat(result.getUpdatedOn()).isNotNull();

사용해야 합니다.

 @Column(name = "created_date", nullable = false, updatable = false)
 
 private LocalDate created = LocalDate.now() ;

언급URL : https://stackoverflow.com/questions/51709727/spring-boot-jpacreateddate-lastmodifieddate-not-being-populated-when-saving-th

반응형