Skip to content

Commit d927e37

Browse files
committed
Add "Testing ORM entity lifecycle callbacks" note to Testing chapter
Closes gh-28228
1 parent 1d302bf commit d927e37

File tree

1 file changed

+80
-1
lines changed

1 file changed

+80
-1
lines changed

src/docs/asciidoc/testing.adoc

+80-1
Original file line numberDiff line numberDiff line change
@@ -5674,7 +5674,6 @@ following example shows the relevant annotations:
56745674

56755675
[[testcontext-tx-false-positives]]
56765676
.Avoid false positives when testing ORM code
5677-
56785677
[NOTE]
56795678
=====
56805679
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:
57965795
----
57975796
=====
57985797

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+
57995878

58005879
[[testcontext-executing-sql]]
58015880
==== Executing SQL Scripts

0 commit comments

Comments
 (0)