@@ -5674,7 +5674,6 @@ following example shows the relevant annotations:
5674
5674
5675
5675
[[testcontext-tx-false-positives]]
5676
5676
.Avoid false positives when testing ORM code
5677
-
5678
5677
[NOTE]
5679
5678
=====
5680
5679
When you test application code that manipulates the state of a Hibernate session or JPA
@@ -5796,6 +5795,86 @@ The following example shows matching methods for JPA:
5796
5795
----
5797
5796
=====
5798
5797
5798
+ [[testcontext-tx-orm-lifecycle-callbacks]]
5799
+ .Testing ORM entity lifecycle callbacks
5800
+ [NOTE]
5801
+ =====
5802
+ Similar to the note about avoiding <<testcontext-tx-false-positives, false positives>>
5803
+ when testing ORM code, if your application makes use of entity lifecycle callbacks (also
5804
+ known as entity listeners), make sure to flush the underlying unit of work within test
5805
+ methods that run that code. Failing to _flush_ or _clear_ the underlying unit of work can
5806
+ result in certain lifecycle callbacks not being invoked.
5807
+
5808
+ For example, when using JPA, `@PostPersist`, `@PreUpdate`, and `@PostUpdate` callbacks
5809
+ will not be called unless `entityManager.flush()` is invoked after an entity has been
5810
+ saved or updated. Similarly, if an entity is already attached to the current unit of work
5811
+ (associated with the current persistence context), an attempt to reload the entity will
5812
+ not result in a `@PostLoad` callback unless `entityManager.clear()` is invoked before the
5813
+ attempt to reload the entity.
5814
+
5815
+ The following example shows how to flush the `EntityManager` to ensure that
5816
+ `@PostPersist` callbacks are invoked when an entity is persisted. An entity listener with
5817
+ a `@PostPersist` callback method has been registered for the `Person` entity used in the
5818
+ example.
5819
+
5820
+ [source,java,indent=0,subs="verbatim,quotes",role="primary"]
5821
+ .Java
5822
+ ----
5823
+ // ...
5824
+
5825
+ @Autowired
5826
+ JpaPersonRepository repo;
5827
+
5828
+ @PersistenceContext
5829
+ EntityManager entityManager;
5830
+
5831
+ @Transactional
5832
+ @Test
5833
+ void savePerson() {
5834
+ // EntityManager#persist(...) results in @PrePersist but not @PostPersist
5835
+ repo.save(new Person("Jane"));
5836
+
5837
+ // Manual flush is required for @PostPersist callback to be invoked
5838
+ entityManager.flush();
5839
+
5840
+ // Test code that relies on the @PostPersist callback
5841
+ // having been invoked...
5842
+ }
5843
+
5844
+ // ...
5845
+ ----
5846
+ [source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
5847
+ .Kotlin
5848
+ ----
5849
+ // ...
5850
+
5851
+ @Autowired
5852
+ lateinit var repo: JpaPersonRepository
5853
+
5854
+ @PersistenceContext
5855
+ lateinit var entityManager: EntityManager
5856
+
5857
+ @Transactional
5858
+ @Test
5859
+ fun savePerson() {
5860
+ // EntityManager#persist(...) results in @PrePersist but not @PostPersist
5861
+ repo.save(Person("Jane"))
5862
+
5863
+ // Manual flush is required for @PostPersist callback to be invoked
5864
+ entityManager.flush()
5865
+
5866
+ // Test code that relies on the @PostPersist callback
5867
+ // having been invoked...
5868
+ }
5869
+
5870
+ // ...
5871
+ ----
5872
+
5873
+ See
5874
+ https://github.com/spring-projects/spring-framework/blob/5.3.x/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/orm/JpaEntityListenerTests.java[JpaEntityListenerTests]
5875
+ in the Spring Framework test suite for working examples using all JPA lifecycle callbacks.
5876
+ =====
5877
+
5799
5878
5800
5879
[[testcontext-executing-sql]]
5801
5880
==== Executing SQL Scripts
0 commit comments