保存对象时未填充Sping Boot JPA@CreatedDate @LastModifiedDate

2w3rbyxf  于 2023-11-19  发布在  Spring
关注(0)|答案(6)|浏览(123)

我正在使用Sping Boot + JPA编写一个应用程序,使用Postgres数据库。我有一个User Entity,我试图在保存和/或修改用户记录时获取时间戳。这不起作用。正在保存的记录对于createdDate和lastModifiedDate都为“null”。
以下是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
)

字符串
我添加日期字段的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)


仍然无法填充时间戳。

fkaflof6

fkaflof61#

@PrePersist@PreUpdate阶段中调用AuditingEntity方法。
这意味着在执行insert或update 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 {

字符串

uoifb46i

uoifb46i2#

我有类似的问题(Sping 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 {


使用的参考文献:

pgx2nnw8

pgx2nnw83#

我也有类似的问题,但我的情况是,我有@Transactional注解的测试类,删除后,一切都按预期工作。

7z5jn7bk

7z5jn7bk4#

我的首选解决方案是一组多个注解,以确保@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();

mcvgt66p

mcvgt66p5#

面对同样的问题,但其他解决方案没有帮助。(我使用Kotlin)然后我意识到我已经将@LastModifiedBy的字段声明为瓦尔,而不是var,即只读。它没有更新失败,只是默默地什么也没做。当我将字段声明更改为var时,它开始正常工作。

u91tlkcl

u91tlkcl6#

你必须使用

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

字符串

相关问题