Four Ways to Fix Spring Boot JSON Serialization ‘no Session’ Error for Associated Entities

This article presents four practical solutions for the Spring Boot 3.5.0 “Could not write JSON: failed to lazily initialize a collection… no Session” error that occurs when serializing bidirectional one-to-many relationships, covering @JsonIgnore, JPQL fetch joins, enabling OpenEntityManagerInView, and using the Jackson Hibernate6 module, with code examples and results.

Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Four Ways to Fix Spring Boot JSON Serialization ‘no Session’ Error for Associated Entities

Environment: Spring Boot 3.5.0

1. Introduction

When serializing entities with bidirectional one-to-many relationships (e.g., Customer and Order) in Spring Boot, the JSON output may fail with the exception “Could not write JSON: failed to lazily initialize a collection… no Session”. The root cause is that the lazy-loaded collection is accessed outside the transaction, so no Hibernate Session is available.

2. Example Entities

@Entity
@Table(name = "t_customer")
public class Customer {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    @OneToMany(mappedBy = "customer", cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval = true)
    private List<Order> orders = new ArrayList<>();
}

@Entity
@Table(name = "t_order")
public class Order {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String orderNumber;
    @ManyToOne
    @JoinColumn(name = "customer_id")
    @JsonIgnore
    private Customer customer;
}

The @JsonIgnore on the customer field prevents infinite recursion but also removes the customer data from the JSON.

2.1 Solution 1 – Use @JsonIgnore

Applying @JsonIgnore to the collection eliminates the lazy-loading exception, but the orders field is completely omitted from the output.

public class Customer {
    // ...
    @OneToMany(mappedBy = "customer", cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval = true)
    @JsonIgnore
    private List<Order> orders = new ArrayList<>();
}

Result:

2.2 Solution 2 – JPQL Fetch Join

Define a custom repository method that uses a JPQL fetch join to load the orders together with the customer.

public interface CustomerRepository extends JpaRepository<Customer, Long> {
    @Query("SELECT e FROM Customer e JOIN FETCH e.orders WHERE e.id = ?1")
    Optional<Customer> findById(Long id);
}

The generated SQL joins t_customer and t_order and retrieves the collection in the same transaction, avoiding the lazy-loading problem.

2.3 Solution 3 – Enable OpenEntityManagerInView

Spring provides the OpenEntityManagerInViewInterceptor. Setting spring.jpa.openInView=true registers this interceptor, which opens a Session for the duration of the web request.

spring:
  jpa:
    openInView: true

When the interceptor is active, the Session is bound to the thread context, allowing lazy collections to be initialized during serialization.

2.4 Solution 4 – Jackson Hibernate6 Module

Add the Jackson Hibernate6 datatype module to the project and register it with the ObjectMapper. The module replaces lazy-loaded entities with null during serialization, preventing the exception.

<dependency>
    <groupId>com.fasterxml.jackson.datatype</groupId>
    <artifactId>jackson-datatype-hibernate6</artifactId>
</dependency>
@Bean
Jackson2ObjectMapperBuilderCustomizer jsonBuilderCustomizer() {
    return builder -> builder.modulesToInstall(modules -> modules.add(new Hibernate6Module()));
}

After configuration, the JSON output contains null for the lazy collection instead of throwing an error.

These four approaches allow developers to choose the most suitable strategy based on whether they need the collection data, want to keep the entity model unchanged, or prefer a global configuration.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

jsonSpring Bootjacksonlazy-loadingjpajpqlhibernate6open-in-view
Spring Full-Stack Practical Cases
Written by

Spring Full-Stack Practical Cases

Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.