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.
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: trueWhen 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.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
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.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
