This project demonstrates the behavior of Spring Boot's Open Session in View (OSIV) feature with spring.jpa.open-in-view=true and false.
It aims to show:
- How OSIV affects connection pool usage under short and long requests.
- The performance impact when multiple concurrent requests are executed.
- The development convenience regarding lazy-loaded relationships.
git clone https://github.com/ercansormaz/spring-osiv-demo.git
cd spring-osiv-demo
mvn spring-boot:runUses H2 in-memory database; no additional setup required.
spring.jpa.open-in-viewdefaults totrue.- HikariCP connection pool configured with maximum pool size = 10.
- Logging enabled for connection acquire/release:
logging.level.com.zaxxer.hikari=DEBUG| Endpoint | Description |
|---|---|
/api/short |
Retrieves data directly from DB |
/api/long |
Retrieves data from DB and simulates a 5-second delay using Thread.sleep |
Use Apache Bench to run load tests:There are two scenarios:
- Concurrency (
-c) > 1 is used, but requests are sent to only one endpoint at a time. - Example:
ab -n 50 -c 50 -r http://localhost:8080/api/long
ab -n 50 -c 50 -r http://localhost:8080/api/short- Purpose: Measure response times of
/shortor/longin isolation.
- Long-running requests are started first (
/long). - Shortly after, in a separate terminal, concurrent requests are sent to
/short. - Example:
ab -n 50 -c 50 http://localhost:8080/api/long
# wait a few seconds
ab -n 50 -c 50 http://localhost:8080/api/short- Purpose: Demonstrate OSIV impact — long requests occupy DB connections, forcing short requests to wait for a free connection.
Single Endpoint Run (OSIV=true):
| Endpoint | 50% | 95% | Max | Notes |
|---|---|---|---|---|
/long |
15s | 25s | 25s | Delay reflected due to Thread.sleep |
/short |
9ms | 11ms | 11ms | Fast, expected |
Parallel Endpoint Run (OSIV=true):
| Endpoint | 50% | 95% | Max | Notes |
|---|---|---|---|---|
/long |
15s | 25s | 25s | Connection pool saturated |
/short |
16ms | 25ms | 19s | Short requests slowed down by long requests 🚨 |
Parallel Endpoint Run (OSIV=false):
| Endpoint | 50% | 95% | Max | Notes |
|---|---|---|---|---|
/long |
5s | 5s | 5s | Connections released immediately |
/short |
12ms | 15ms | 15ms | Unaffected by long requests ✅ |
| Feature | OSIV=true | OSIV=false |
|---|---|---|
| Connection release | At request completion | At transaction completion |
| Connection pool usage | High for long requests | Low (isolated transactions) |
| Short request latency | Can spike significantly under load | Stable |
| PROD suitability | ✅ Safe | |
| Development convenience | ✅ Easy lazy-loading in controllers |
- With OSIV=true, lazy-loaded relations can be accessed even in any layer.
- With OSIV=false, accessing lazy relations outside the transactional boundary will throw:
org.hibernate.LazyInitializationException: failed to lazily initialize collectionRecommended approach for OSIV=false:
-
Load all necessary lazy relations inside the service layer using:
- Fetch join (
JOIN FETCHin JPQL) - Entity Graphs (
@EntityGraph) - DTO projection (Spring Data projections)
- Fetch join (
-
This approach avoids LazyInitializationException while keeping production safe.
🔹 Note: Lazy-loading demonstration will be implemented in a separate branch. The main branch README already describes this scenario, so no separate README is needed in that branch.
This repository also includes a lazy-loading demonstration available in a separate branch (lazy-loading).
That example shows how spring.jpa.open-in-view affects the behavior of @OneToMany and @ManyToOne relationships:
| Scenario | OSIV | Result |
|---|---|---|
| Accessing lazy relations in Controller | true | ✅ Works (but keeps connection open until response) |
| Accessing lazy relations in Controller | false | ❌ Throws LazyInitializationException |
Using @EntityGraph or fetch join |
false | ✅ Works safely |
The branch contains:
- A
DummyParent↔DummyChildentity pair with a lazy@OneToManyrelationship - Controller endpoints demonstrating both failing and safe approaches
- A simple
@EntityGraphexample as the recommended fix
For details, check the
lazy-loadingbranch in this repository
- OSIV=true: Development convenience high, but high risk under production load.
- OSIV=false: Production safe, requires slightly more coding to handle lazy-loaded entities.
- Lazy-loading demo will be shown in a dedicated branch using the techniques described above.
You can read a detailed explanation of this project in the blog post here:
👉 Read the Blog Post
Contributions are welcome! Feel free to fork the repo, submit pull requests or open issues.
This project is licensed under the MIT License.