Home > Net >  Could not write JSON: failed to lazily initialize a collection of role. When I remove @JsonManagedRe
Could not write JSON: failed to lazily initialize a collection of role. When I remove @JsonManagedRe

Time:04-12

I am having an error with the fetch type and I dont know how to fix it! I retried to solve with similar issue solutions, but didn't work. Using java 11, Spring boot 2.6.5, gradle

MenuController:

package com.magsad.msnav.controller;

import com.magsad.msnav.entity.Menu;
import com.magsad.msnav.service.MenuService;
import lombok.AccessLevel;
import lombok.RequiredArgsConstructor;
import lombok.experimental.FieldDefaults;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

@RestController
@RequestMapping("menu")
@RequiredArgsConstructor
@FieldDefaults(makeFinal = true,level = AccessLevel.PRIVATE)
public class MenuController {
    MenuService menuService;

    @GetMapping
    public List<Menu> getAllNodes(){
        return menuService.getAll();
    }

    @GetMapping("{nodeId}")
    public Menu getNodeById(@PathVariable Long nodeId){
        return menuService.getById(nodeId);
    }

    @GetMapping("query")
    public Menu getNodeByIdQuery(@RequestParam Long nodeId){
        return menuService.getById(nodeId);
    }

    @PostMapping
    public Menu create(@RequestBody Menu menu){
        return menuService.create(menu);
    }

    @PutMapping
    public Menu update(@RequestBody Menu menu){
        return menuService.update(menu);
    }

    @DeleteMapping("{id}")
    public void delete(@PathVariable Long nodeId){
        menuService.delete(nodeId);
    }
}

Menu entity

import com.fasterxml.jackson.annotation.JsonBackReference;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonManagedReference;
import lombok.*;

import javax.persistence.*;
import java.util.List;
import java.util.Set;


@Data
@AllArgsConstructor
@NoArgsConstructor
@Entity
@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class Menu implements Serializable {

    private static final long serialVersionUID = 1L;


    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    @Column(name = "url", nullable = false)
    private String url;

    @Column(name = "name")
    private String name;

    @JsonManagedReference
    @OneToMany(mappedBy="parent")
    private Set<Menu> children = new HashSet<>();

    @ManyToOne
    @JsonBackReference
    private Menu parent;
}

When I remove @JsonManagedReference and @JsonBackReference and add @JsonIgnore to private Set<Menu> children = new HashSet<>() it works.

//    @JsonManagedReference
    @OneToMany(mappedBy="parent")
    @JsonIgnore
    private Set<Menu> children = new HashSet<>();

    @ManyToOne
//    @JsonBackReference
    private Menu parent;

MenuRepository

import com.magsad.msnav.entity.Menu;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface MenuRepository extends JpaRepository<Menu,Long> {
}

MenuService

import com.magsad.msnav.entity.Menu;
import com.magsad.msnav.repository.MenuRepository;
import lombok.AccessLevel;
import lombok.RequiredArgsConstructor;
import lombok.experimental.FieldDefaults;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;

@Service
@RequiredArgsConstructor
@FieldDefaults(makeFinal = true,level = AccessLevel.PRIVATE)
@Transactional
public class MenuService {
    MenuRepository menuRepository;

    public List<Menu> getAll() {
        return menuRepository.findAll();
/*                .stream()
                .filter(menu-> Objects.isNull(menu.getParent()))
                .collect(Collectors.toList());*/
    }

    public Menu getById(Long nodeId){
        return menuRepository.findById(nodeId).get();
    }

    public Menu create(Menu menu){
        return menuRepository.save(menu);
    }

    public Menu update(Menu menu){
        Menu menuForUpdate = menuRepository.findById(menu.getId()).get();
        menuForUpdate.setId(menu.getId());
        menuForUpdate.setName(menu.getName());
        menuForUpdate.setUrl(menu.getUrl());
        return menuRepository.save(menuForUpdate);
    }

    public void delete(Long nodeId) {
        menuRepository.deleteById(nodeId);
    }

}

I tried similar issue solutions again and again but failed to solve.

entityGraph, Eager Lazy, config

Could not write JSON: failed to lazily initialize a collection of role:

https://www.netsurfingzone.com/hibernate/failed-to-lazily-initialize-a-collection-of-role-could-not-initialize-proxy-no-session/

https://github.com/FasterXML/jackson-core/issues/469

CodePudding user response:

When creating the Json objects, if you don't specify a @JsonIgnore and/or @JsonBackReference property on a relationship attribut. This is done so that one Object doesn't generate the other one over and over, it could easely become an infinite loop and you will never get the response to your query.
@JsonIgnore tell jpa to not put the children list into the Json to stop the infinite loop from happening.

CodePudding user response:

I just removed @Data annotation, instead of it I wrote @Getter @Setter @ToString @EqualsAndHashCode, added @OneToMany(mappedBy = "parent",fetch = FetchType.EAGER)and worked !

  • Related