eBook – Guide Spring Cloud – NPI EA (cat=Spring Cloud)
announcement - icon

Let's get started with a Microservice Architecture with Spring Cloud:

>> Join Pro and download the eBook

eBook – Mockito – NPI EA (tag = Mockito)
announcement - icon

Mocking is an essential part of unit testing, and the Mockito library makes it easy to write clean and intuitive unit tests for your Java code.

Get started with mocking and improve your application tests using our Mockito guide:

Download the eBook

eBook – Java Concurrency – NPI EA (cat=Java Concurrency)
announcement - icon

Handling concurrency in an application can be a tricky process with many potential pitfalls. A solid grasp of the fundamentals will go a long way to help minimize these issues.

Get started with understanding multi-threaded applications with our Java Concurrency guide:

>> Download the eBook

eBook – Reactive – NPI EA (cat=Reactive)
announcement - icon

Spring 5 added support for reactive programming with the Spring WebFlux module, which has been improved upon ever since. Get started with the Reactor project basics and reactive programming in Spring Boot:

>> Join Pro and download the eBook

eBook – Java Streams – NPI EA (cat=Java Streams)
announcement - icon

Since its introduction in Java 8, the Stream API has become a staple of Java development. The basic operations like iterating, filtering, mapping sequences of elements are deceptively simple to use.

But these can also be overused and fall into some common pitfalls.

To get a better understanding on how Streams work and how to combine them with other language features, check out our guide to Java Streams:

>> Join Pro and download the eBook

eBook – Jackson – NPI EA (cat=Jackson)
announcement - icon

Do JSON right with Jackson

Download the E-book

eBook – HTTP Client – NPI EA (cat=Http Client-Side)
announcement - icon

Get the most out of the Apache HTTP Client

Download the E-book

eBook – Maven – NPI EA (cat = Maven)
announcement - icon

Get Started with Apache Maven:

Download the E-book

eBook – Persistence – NPI EA (cat=Persistence)
announcement - icon

Working on getting your persistence layer right with Spring?

Explore the eBook

eBook – RwS – NPI EA (cat=Spring MVC)
announcement - icon

Building a REST API with Spring?

Download the E-book

Course – LS – NPI EA (cat=Jackson)
announcement - icon

Get started with Spring and Spring Boot, through the Learn Spring course:

>> LEARN SPRING
Course – RWSB – NPI EA (cat=REST)
announcement - icon

Explore Spring Boot 3 and Spring 6 in-depth through building a full REST API with the framework:

>> The New “REST With Spring Boot”

Course – LSS – NPI EA (cat=Spring Security)
announcement - icon

Yes, Spring Security can be complex, from the more advanced functionality within the Core to the deep OAuth support in the framework.

I built the security material as two full courses - Core and OAuth, to get practical with these more complex scenarios. We explore when and how to use each feature and code through it on the backing project.

You can explore the course here:

>> Learn Spring Security

Course – LSD – NPI EA (tag=Spring Data JPA)
announcement - icon

Spring Data JPA is a great way to handle the complexity of JPA with the powerful simplicity of Spring Boot.

Get started with Spring Data JPA through the guided reference course:

>> CHECK OUT THE COURSE

Partner – Moderne – NPI EA (cat=Spring Boot)
announcement - icon

Refactor Java code safely — and automatically — with OpenRewrite.

Refactoring big codebases by hand is slow, risky, and easy to put off. That’s where OpenRewrite comes in. The open-source framework for large-scale, automated code transformations helps teams modernize safely and consistently.

Each month, the creators and maintainers of OpenRewrite at Moderne run live, hands-on training sessions — one for newcomers and one for experienced users. You’ll see how recipes work, how to apply them across projects, and how to modernize code with confidence.

Join the next session, bring your questions, and learn how to automate the kind of work that usually eats your sprint time.

Course – LJB – NPI EA (cat = Core Java)
announcement - icon

Code your way through and build up a solid, practical foundation of Java:

>> Learn Java Basics

1. Overview

While using lazy loading in Hibernate, we might face exceptions, saying there is no session.

In this tutorial, we’ll discuss how to solve these lazy loading issues. To do this, we’ll use Spring Boot to explore an example.

2. Lazy Loading Issues

The aim of lazy loading is to save resources by not loading related objects into memory when we load the main object. Instead, we postpone the initialization of lazy entities until the moment they’re needed. Hibernate uses proxies and collection wrappers to implement lazy loading.

When retrieving lazily-loaded data, there are two steps in the process. First, there’s populating the main object, and second, retrieving the data within its proxies. Loading data always requires an open Session in Hibernate.

The problem arises when the second step happens after the transaction has closed, which leads to a LazyInitializationException.

The recommended approach is to design our application to ensure that data retrieval happens in a single transaction. But, this can sometimes be difficult when using a lazy entity in another part of the code that is unable to determine what has or hasn’t been loaded.

Hibernate has a workaround, an enable_lazy_load_no_trans property. Turning this on means that each fetch of a lazy entity will open a temporary session and run inside a separate transaction.

3. Lazy Loading Example

Let’s look at the behavior of lazy loading under a few scenarios.

3.1. Set Up Entities and Services

Suppose we have two entities, User and Document. One User may have many Documents, and we’ll use @OneToMany to describe that relationship. Also, we’ll use @Fetch(FetchMode.SUBSELECT) for efficiency.

We should note that, by default, @OneToMany has a lazy fetch type.

Let’s now define our User entity:

@Entity
public class User {

    // other fields are omitted for brevity

    @OneToMany(mappedBy = "userId")
    @Fetch(FetchMode.SUBSELECT)
    private List<Document> docs = new ArrayList<>();
}

Next, we need a service layer with two methods to illustrate the different options. One of them is annotated as @Transactional. Here, both methods perform the same logic by counting all documents from all users:

@Service
public class ServiceLayer {

    @Autowired
    private UserRepository userRepository;

    @Transactional(readOnly = true)
    public long countAllDocsTransactional() {
        return countAllDocs();
    }

    public long countAllDocsNonTransactional() {
        return countAllDocs();
    }

    private long countAllDocs() {
        return userRepository.findAll()
            .stream()
            .map(User::getDocs)
            .mapToLong(Collection::size)
            .sum();
    }
}

Now, let’s take a closer look at the following three examples. We’ll also use SQLStatementCountValidator to understand the efficiency of the solution, by counting the number of queries executed.

3.2. Lazy Loading With a Surrounding Transaction

First of all, let’s use lazy loading in the recommended way. So, we’ll call our @Transactional method in the service layer:

@Test
public void whenCallTransactionalMethodWithPropertyOff_thenTestPass() {
    SQLStatementCountValidator.reset();

    long docsCount = serviceLayer.countAllDocsTransactional();

    assertEquals(EXPECTED_DOCS_COLLECTION_SIZE, docsCount);
    SQLStatementCountValidator.assertSelectCount(2);
}

As we can see, this works and results in two roundtrips to the database. The first roundtrip selects users, and the second selects their documents.

3.3. Lazy Loading Outside of a Transaction

Now, let’s call a non-transactional method to simulate the error we get without a surrounding transaction:

@Test(expected = LazyInitializationException.class)
public void whenCallNonTransactionalMethodWithPropertyOff_thenThrowException() {
    serviceLayer.countAllDocsNonTransactional();
}

As predicted, this results in an error as the getDocs function of User is used outside of a transaction.

3.4. Lazy Loading With Automatic Transaction

To fix that, we can enable the property:

spring.jpa.properties.hibernate.enable_lazy_load_no_trans=true

With the property turned on, we no longer get a LazyInitializationException.

However, the count of the queries shows that six roundtrips have been made to the database. Here, one roundtrip selects users, and five roundtrips select documents for each of five users:

@Test
public void whenCallNonTransactionalMethodWithPropertyOn_thenGetNplusOne() {
    SQLStatementCountValidator.reset();
    
    long docsCount = serviceLayer.countAllDocsNonTransactional();
    
    assertEquals(EXPECTED_DOCS_COLLECTION_SIZE, docsCount);
    SQLStatementCountValidator.assertSelectCount(EXPECTED_USERS_COUNT + 1);
}

We’ve run into the notorious N + 1 issue, despite the fact that we set a fetch strategy to avoid it!

4. Comparing the Approaches

Let’s briefly discuss the pros and cons.

With the property turned on, we don’t have to worry about transactions and their boundaries. Hibernate manages that for us.

However, the solution works slowly, because Hibernate starts a transaction for us on each fetch.

It works perfectly for demos and when we don’t care about performance issues. This may be ok if used to fetch a collection that contains only one element, or a single related object in a one to one relationship.

Without the property, we have fine-grained control of the transactions, and we no longer face performance issues.

Overall, this is not a production-ready feature, and the Hibernate documentation warns us:

Although enabling this configuration can make LazyInitializationException go away, it’s better to use a fetch plan that guarantees that all properties are properly initialized before the Session is closed.

5. Conclusion

In this tutorial, we explored dealing with lazy loading.

We tried a Hibernate property to help overcome the LazyInitializationException. We also saw how it reduces efficiency and may only be a viable solution for a limited number of use cases.

The code backing this article is available on GitHub. Once you're logged in as a Baeldung Pro Member, start learning and coding on the project.
Baeldung Pro – NPI EA (cat = Baeldung)
announcement - icon

Baeldung Pro comes with both absolutely No-Ads as well as finally with Dark Mode, for a clean learning experience:

>> Explore a clean Baeldung

Once the early-adopter seats are all used, the price will go up and stay at $33/year.

eBook – HTTP Client – NPI EA (cat=HTTP Client-Side)
announcement - icon

The Apache HTTP Client is a very robust library, suitable for both simple and advanced use cases when testing HTTP endpoints. Check out our guide covering basic request and response handling, as well as security, cookies, timeouts, and more:

>> Download the eBook

eBook – Java Concurrency – NPI EA (cat=Java Concurrency)
announcement - icon

Handling concurrency in an application can be a tricky process with many potential pitfalls. A solid grasp of the fundamentals will go a long way to help minimize these issues.

Get started with understanding multi-threaded applications with our Java Concurrency guide:

>> Download the eBook

eBook – Java Streams – NPI EA (cat=Java Streams)
announcement - icon

Since its introduction in Java 8, the Stream API has become a staple of Java development. The basic operations like iterating, filtering, mapping sequences of elements are deceptively simple to use.

But these can also be overused and fall into some common pitfalls.

To get a better understanding on how Streams work and how to combine them with other language features, check out our guide to Java Streams:

>> Join Pro and download the eBook

eBook – Persistence – NPI EA (cat=Persistence)
announcement - icon

Working on getting your persistence layer right with Spring?

Explore the eBook

Course – LS – NPI EA (cat=REST)

announcement - icon

Get started with Spring Boot and with core Spring, through the Learn Spring course:

>> CHECK OUT THE COURSE

Partner – Moderne – NPI EA (tag=Refactoring)
announcement - icon

Modern Java teams move fast — but codebases don’t always keep up. Frameworks change, dependencies drift, and tech debt builds until it starts to drag on delivery. OpenRewrite was built to fix that: an open-source refactoring engine that automates repetitive code changes while keeping developer intent intact.

The monthly training series, led by the creators and maintainers of OpenRewrite at Moderne, walks through real-world migrations and modernization patterns. Whether you’re new to recipes or ready to write your own, you’ll learn practical ways to refactor safely and at scale.

If you’ve ever wished refactoring felt as natural — and as fast — as writing code, this is a good place to start.

eBook Jackson – NPI EA – 3 (cat = Jackson)