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

后端 未结 4 1170
南笙
南笙 2021-01-17 23:21

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.

相关标签:
4条回答
  • 2021-01-17 23:48

    The AuditingEntityListener methods are called in the @PrePersist and @PreUpdate phase.

    This means they are called just before the insert or update SQL statements are executed.

    Read more about JPA events in the Hibernate doc: https://docs.jboss.org/hibernate/orm/5.2/userguide/html_single/Hibernate_User_Guide.html#events-jpa-callbacks

    Unit Tests

    When using in Tests you have to enable auditing as well on the test

    @DataJpaTest
    @RunWith(SpringRunner.class)
    @EnableJpaAuditing
    public class EntityListenerTest {
    
    0 讨论(0)
  • 2021-01-17 23:48

    I had similar issue, but the reason for my case is that I had @Transactional annotation on the test class, after removing that, everything works as expected.

    0 讨论(0)
  • 2021-01-17 23:55

    I had similar issue (Spring Boot 2.2.1 and JUnit5) with null values. Adding @EnableJpaAuditing to test class did not work.

    My example (did not copy everything):

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

    and respective class:

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

    I had following configuration for auditing:

    @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() {
    

    To get @CreatedBy and @CreatedDate working inside test only @Import was needed

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

    Used references:

    • 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

    0 讨论(0)
  • 2021-01-18 00:04

    My prefered solution is a set of multiple annotations to ensure test of @CreatedBy or @CreatedDate:

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

    My Entities looks like:

    @MappedSuperclass
    @EntityListeners(AuditingEntityListener.class)
    public class AbstractEntity {
    
        @CreatedBy
        private String createdBy;
    
        @CreatedDate
        private Date createdOn;
    
        @LastModifiedDate
        private Date updatedOn;
    
        @LastModifiedBy
        private String updatedBy;
    }
    

    My JPA configuration is:

    @Configuration
    @EnableJpaAuditing(auditorAwareRef = "auditorAware")
    public class JPAConfig {
    
        @Bean
        public AuditorAware<String> auditorAware() {
            return () -> Optional.of(((User)     SecurityContextHolder.getContext().getAuthentication().getPrincipal()).getUsername());
        }
    }
    

    Now your audit fields also created during JPA test:

    assertThat(result.getCreatedBy()).isNotNull().isEqualTo("testuser");
    assertThat(result.getCreatedOn()).isNotNull();
    assertThat(result.getUpdatedBy()).isNotNull().isEqualTo("testuser");
    assertThat(result.getUpdatedOn()).isNotNull();
    
    0 讨论(0)
提交回复
热议问题