当前位置: 首页 > 知识库问答 >
问题:

保存对象时未填充Spring BootJPA@CreatedDate@LastModifiedDate

梁嘉祥
2023-03-14

我正在用Spring Boot JPA编写一个应用程序,使用Postgres数据库。我有一个用户实体,我试图在保存和/或修改用户记录时获取时间戳。这不起作用。正在保存的记录的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)

仍然没有填充时间戳。

共有3个答案

司徒俊健
2023-03-14

我也有类似的问题,但我之所以这样做,是因为我在测试类上有了事务性注释,在删除该注释后,一切都按预期进行。

郭思聪
2023-03-14

我也有类似的问题(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;
}

以及相应的类别:

@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在测试中工作,只需要@导入

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

使用的参考文献:

>

  • https://springbootdev.com/2018/03/13/spring-data-jpa-auditing-with-createdby-createddate-lastmodifiedby-and-lastmodifieddate/

    https://github.com/spring-projects/spring-boot/issues/10743#issuecomment-416777423

  • 奚才良
    2023-03-14

    AuditingEntityListener方法在PrePersist和PreUpdate阶段调用。

    这意味着在执行insert或update SQL语句之前调用它们。

    阅读Hibernate文档中有关JPA事件的更多信息:https://docs.jboss.org/hibernate/orm/5.2/userguide/html_single/Hibernate_User_Guide.html#events-jpa回调

    单元测试

    在测试中使用时,还必须在测试中启用审核

    @DataJpaTest
    @RunWith(SpringRunner.class)
    @EnableJpaAuditing
    public class EntityListenerTest {
    
     类似资料:
    • 同样,在导出时没有错误。问题是getCityWeatherbyZipresponse.getCityWeatherbyZipResult的值为null。我知道文档正在返回正确的结果,因为结果打印如下: 结果打印输出: 测试Web服务:http://wsf.cdyne.com/weatherws/weather.asmx 子umarshal对象:

    • 问题内容: 我无法手动或自动在新保存的对象上填充创建者字段……我能找到的唯一方法是重新查询我已经想要做的对象。 这是设置: 这是我拉头发的地方 编辑:最新的猫鼬解决了此问题并添加了填充功能,请参见新的接受的答案。 问题答案: 您应该能够使用模型的填充函数来执行此操作:http : //mongoosejs.com/docs/api.html#model_Model.populate 在书籍的保存处

    • 我有一个要填充信息的对象。我从许多不同的服务中检索信息。我做了一个助手类,它有一个公共方法,然后有许多私有方法来调用服务。我写的东西很好,但我不确定这是否是正确的方法。 您可能想知道为什么我需要一个包含所有这些信息的对象。我需要它全部在一个对象中,因为我从这个java对象创建了一个json对象并将其传递给javascript层。 我的方法有什么问题?我是否应该遵循一种编程范式来做这样的事情? 例子

    • 问题内容: 我有一个带有created_by字段的模型,该模型链接到标准Django用户模型。保存模型时,我需要使用当前用户的ID自动填充它。我无法在Admin层执行此操作,因为该网站的大部分内容都不会使用内置的Admin。谁能建议我该怎么做? 问题答案: 如果你希望某些东西在管理员和其他地方都可以使用,则应使用自定义模型形式。基本思想是重写该__init__方法以采用一个额外的参数-reques

    • 问题内容: 我有抽象类Human,这是另外两个类Student和Worker的延伸。我正在尝试填写两个数组列表。类型为Student的ArrayList和类型为Worker的ArrayList动态。 } } } } 问题答案: 当然,只需添加学生: 您可以为工人做几乎完全相同的事情。如果要使用循环,请执行以下操作: 这将创建一个新学生列表,其姓名后面有不同的编号。但是,如果您需要其他数据,则该数据

    • 问题内容: 使用mongoosejs填充和直接对象包含之间是否有性能差异(查询的处理时间)?什么时候应该使用? 猫鼬人口的例子: 猫鼬对象嵌套示例: 问题答案: 关于猫鼬种群的第一件事,是要了解它不是魔术,而只是一种方便的方法,它使您无需亲自完成所有操作即可检索相关信息。 该概念主要用于以下情况:您决定需要将数据放置在单独的集合中,而不是将数据嵌入其中,并且主要考虑因素通常应在文档大小上,或者在相