spring-projects / spring-projects/spring-data-jpa

Different EntityManager context behavior between SimpleJpaRepository methods and derived query methods when using separate Rw/Ro EntityManagers inside a @Transactional boundary

Open
#4,107 6 comments 0 reactions 1 assignee View on GitHub

@christophstrobl is already working on this.

Since Dec 1, 2025.

status: waiting-for-triage
Dominant language
Java
Stars
3.3k
Forks
1.6k
PR merge metrics
No merged PRs in 30d

Description

🧩 Summary

When calling a RoRepository (using a read-only EntityManager) within a @Transactional method that uses a Rw (read-write) EntityManager, the behavior differs depending on whether the repository method is:

A method implemented by SimpleJpaRepository (e.g., findById, getReferenceById), or

A derived query method (method-name-based JPQL generation).

This difference leads to inconsistent persistence context behavior and affects lazy loading.

Reproduction repository:
👉 https://github.com/iks15174/jpa-test

🧪 Reproduction Behavior

1. Using SimpleJpaRepository methods (e.g., findById)

The entity loads successfully.

But accessing a lazy-loaded association triggers:

LazyInitializationException

This happens because the Ro EntityManager's persistence context is closed immediately after the method call.

2. Using derived query methods

The entity loads successfully.

Lazy-loaded associations work normally.

The Ro EntityManager remains active, and its persistence context participates properly.

🔍 Observed Cause

Based on investigation, the behavior difference appears to be:

Inside an active @Transactional method using the Rw EntityManager, calling a RoRepository method behaves differently depending on the type of repository method:

✔ Case 1: SimpleJpaRepository methods

The Ro EntityManager does not join the existing transactional context.

Its persistence context is not propagated upward.

After the repository method returns, the Ro persistence context is immediately closed.

Therefore, the subsequent lazy loading fails.

✔ Case 2: Derived query methods

The Ro EntityManager remains active after the query execution.

Lazy loading works because the Ro persistence context stays open.

This results in two different behaviors for the same RoRepository depending solely on which type of repository method is invoked.

❓ Question

I would like to understand whether this difference is intentional or unexpected.

If this behavior is intentional:

What is the design rationale behind treating SimpleJpaRepository methods and derived query methods differently in terms of persistence context lifecycle and EntityManager participation?

If this is not intentional:

Is this a candidate for improvement or unification so that both method types behave consistently?

📎 Additional Information

Reproduction project demonstrating the issue:
🔗 https://github.com/iks15174/jpa-test

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.