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 anhashCode()
implementation calculating the hashCode based on all properties of that class.That means that the hashCode method in your
Toy
class invokes thehasCode
method onCat
. In cat there is aSet
ofCatFoods
which is mapped byCat
which means that to calculate thehashCode
ofcatFoods
theCat
property is involved. To calculate the hashCode of Cat it begins again calculating thehashCode
of theSet
ofCatFoods
(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.