Spring Boot JPA@CreatedDate @LastModifiedDate not being populated when saving the object

DAr*_*rkO 5 spring spring-data-jpa kotlin spring-boot

I am writing an app with Spring Boot + JPA, using a Postgres database. I have a User Entity and I am trying to get a timestamp when the user record is saved and/or modified. This is not working. The record that is being saved has "null" for both createdDate and lastModifiedDate.

Here is all the relevant code in Kotlin:

@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
)
Run Code Online (Sandbox Code Playgroud)

My SQL queries to add the date fields look like this:

ALTER TABLE app_user
ADD COLUMN last_modified_date TIMESTAMP,
ADD COLUMN created_date TIMESTAMP;
Run Code Online (Sandbox Code Playgroud)

I also have a configuration class

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

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

}
Run Code Online (Sandbox Code Playgroud)

And my test class:

  @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()
        }
    }
Run Code Online (Sandbox Code Playgroud)

UPDATE:

It seems the problem only happens in tests. It seems to be fine when i execute the same code to create a user in the development environment and not in tests.

Do i need some additional config in the tests?

UPDATE 2

I also tried to use the entity manager like this:

@Autowired
lateinit var entityManager: TestEntityManager
Run Code Online (Sandbox Code Playgroud)

Then in the test do:

entityManager.persist(user)
entityManager.flush()
Run Code Online (Sandbox Code Playgroud)

And also

entityManager.persistAndFlush(user)
Run Code Online (Sandbox Code Playgroud)

Still is not populating the timestamps.

Sim*_*lli 10

@PrePersist@PreUpdate阶段调用AuditingEntityListener方法。

这意味着它们将在执行插入或更新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 {
Run Code Online (Sandbox Code Playgroud)


小智 8

我的值也有类似的问题(Spring Boot 2.2.1 和 JUnit5)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;
}
Run Code Online (Sandbox Code Playgroud)

以及各自的班级:

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

我有以下审计配置:

@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() {
Run Code Online (Sandbox Code Playgroud)

@CreatedBy只需要进行@CreatedDate内部测试@Import即可

@DataJpaTest
@Import(JpaAuditingConfiguration.class)
class SurveyRecordRepositoryTest {
Run Code Online (Sandbox Code Playgroud)

使用的参考资料: