Message Could not write JSON: failed to lazily initialize a collection of role: core.domain.Cat.catFoods, could not initialize proxy - no Session; nested exception is com.fasterxml.jackson.databind.JsonMappingException: failed to lazily initialize a collection of role: core.domain.Cat.catFoods, could not initialize proxy - no Session (through reference chain: web.dto.ToysDTO["toys"]->java.util.HashSet[0]->web.dto.ToyDTO["cat"]->core.domain.Cat["catFoods"])
Description The server encountered an unexpected condition that prevented it from fulfilling the request.
I have the following entities: Toy, Cat, CatFood and Food. Basically Cat with Toy are in 1:1 relation and Cat and Food are in m:n relation using CatFood.
@NamedEntityGraphs({
@NamedEntityGraph(name = "toyWithCat",
attributeNodes = @NamedAttributeNode(value = "cat"))
})
@NoArgsConstructor
@AllArgsConstructor
@Data
@ToString
@EqualsAndHashCode(callSuper = true)
@Entity
public class Toy extends BaseEntity<Long> {
String name;
int size;
public Toy(Long id, String name, int size) {
this.setId(id);
this.name = name;
this.size = size;
}
@JsonBackReference(value = "cat-reference")
@OneToOne(mappedBy = "favoriteToy")
private Cat cat;
}
@NamedEntityGraphs({
@NamedEntityGraph(name = "catWithToy",
attributeNodes = @NamedAttributeNode(value = "favoriteToy")),
@NamedEntityGraph(name = "catWithCatFoodAndFood",
attributeNodes = @NamedAttributeNode(value = "catFoods",
subgraph = "catFoodWithFood"),
subgraphs = @NamedSubgraph(name = "catFoodWithFood",
attributeNodes = @NamedAttributeNode(value = "food")))
})
@Entity
public class Cat extends BaseEntity<Long> {
String name, breed;
Integer catYears;
@JsonManagedReference(value = "cat-reference")
@OneToOne(fetch = FetchType.LAZY, cascade = {CascadeType.ALL}, orphanRemoval = true)
@JoinColumn(name = "toy_id", referencedColumnName = "id")
private Toy favoriteToy;
@JsonManagedReference(value = "cat-reference")
@OneToMany(fetch = FetchType.LAZY, mappedBy = "cat", cascade = {CascadeType.REMOVE}, orphanRemoval = true)
Set<CatFood> catFoods;
And I am trying to call this function
public interface ToyRepository extends Repository<Toy, Long> {
@Query("select distinct t from Toy t")
@EntityGraph(value = "toyWithCat", type = EntityGraph.EntityGraphType.LOAD)
List<Toy> getToysWithCat();
}
I am using the same idea on fetching cats with toys as the toy entity does not have another relation and they are loaded without a problem
In your Toy
class you are using @EqualsAndHashCode
which will be resolved in an hashCode()
implementation calculating the hashCode based on all properties of that class.
That means that the hashCode method in your Toy
class invokes the hasCode
method on Cat
. In cat there is a Set
of CatFoods
which is mapped by Cat
which means that to calculate the hashCode
of catFoods
the Cat
property is involved. To calculate the hashCode of Cat it begins again calculating the hashCode
of the Set
of CatFoods
(Sounds confusing but currently I am unable to describe it better)
As there is no session active the Lazy collection can not be fetched which is required to calculate the hashCod. Thats why you get this exception.
Takeaway: explicitly exclude LAZY
fetched properties from @EqualsAndHashCode
calculation. You can annotate these properties using @EqualsAndHashCode.Exclude
to exclude them from the hashCode calculation.
To see implementation of the hashCode calculation you can use the DeLombok functionality of IntelliJ.