Spring Boot JPA@CreatedDate @LastModifiedDate n'est pas renseigné lors de l'enregistrement de l'objet

J'écris une application avec Spring Boot + JPA, en utilisant une base de données Postgres. J'ai une entité utilisateur et j'essaie d'obtenir un horodatage lorsque l'enregistrement de l'utilisateur est enregistré et/ou modifié. Cela ne fonctionne pas. L'enregistrement en cours de sauvegarde a "null" pour les deux createdDate et lastModifiedDate.

Voici tout le code pertinent dans 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
)

Mes requêtes SQL pour ajouter les champs de date ressemblent à ceci :

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

J'ai aussi une classe de configuration

@Configuration
@EnableJpaAuditing(auditorAwareRef = "auditorProvider")
class JpaAuditingConfiguration {
@Bean
fun auditorProvider(): AuditorAware<String> {
return AuditorAware { Optional.of(SecurityContextHolder.getContext().authentication.name) }
}
}

Et ma classe de test:

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

METTRE À JOUR:

Il semble que le problème ne se produise que dans les tests. Il semble bien que j'exécute le même code pour créer un utilisateur dans l'environnement de développement et non dans les tests.

Ai-je besoin d'une configuration supplémentaire dans les tests ?

MISE À JOUR 2

J'ai aussi essayé d'utiliser le gestionnaire d'entités comme ceci:

@Autowired
lateinit var entityManager: TestEntityManager

Ensuite, dans le test, faites:

entityManager.persist(user)
entityManager.flush()

Et aussi

entityManager.persistAndFlush(user)

Ne remplit toujours pas les horodatages.


Solution du problème

Les méthodes AuditingEntityListener sont appelées dans les phases @PrePersistet.@PreUpdate

Cela signifie qu'ils sont appelés juste avant l'exécution des instructions SQL d'insertion ou de mise à jour.

En savoir plus sur les événements JPA dans la documentation Hibernate :
https://docs.jboss.org/hibernate/orm/5.2/userguide/html_single/Hibernate_User_Guide.html#events-jpa-callbacks

Tests unitaires

Lors de l'utilisation dans les tests, vous devez également activer l'audit sur le test

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

Commentaires

Posts les plus consultés de ce blog

La fonction GCP Cloud pour écrire des données dans BigQuery s'exécute avec succès, mais les données n'apparaissent pas dans la table BigQuery

Erreur Symfony : "Une exception a été levée lors du rendu d'un modèle"

Le shell POSIX (sh) redirige stderr vers stdout et capture stderr et stdout dans des variables