2015-10-11 1 views
1

J'ai un problème avec la réponse de repos lorsque j'utilise l'annotation ManyToMany. problème est cette réponse:Spring Data Rest FetchType

Problem accessing /json2/1. Reason: 

    Server Error 

Caused by: 

org.springframework.http.converter.HttpMessageNotWritableException: Could not write JSON: failed to lazily initialize a collection of role: com.Tomek.entity.User.roles, could not initialize proxy - no Session (through reference chain: java.util.ArrayList[0]->com.Tomek.entity.Role["users"]->org.hibernate.collection.internal.PersistentBag[0]->com.Tomek.entity.User["roles"]); nested exception is com.fasterxml.jackson.databind.JsonMappingException: failed to lazily initialize a collection of role: com.Tomek.entity.User.roles, could not initialize proxy - no Session (through reference chain: java.util.ArrayList[0]->com.Tomek.entity.Role["users"]->org.hibernate.collection.internal.PersistentBag[0]->com.Tomek.entity.User["roles"]) 

Sans annotation ManyToMany (comme dans le rôle de la classe Model) Je réponse JSON

[{"id":1,"name":"ROLE_USER"},{"id":2,"name":"ROLE_ADMIN"}] 

RestController

@Controller 
public class RestController { 

    @Autowired 
    private UserService userService; 

    @Autowired 
    private BlogService blogService; 

    @Autowired 
    private RoleService roleService; 

@RequestMapping("/json") 
    public String JsonLink(Model model){ 
     model.addAttribute("result", blogService.findAll()); 
     return "json"; 
    } 

    @RequestMapping(value = "/json2/{id}", method = RequestMethod.GET, produces=MediaType.APPLICATION_JSON_VALUE) 
    public @ResponseBody List<Role> ShowJson(@PathVariable int id) { 
     Hibernate.initialize(roleService.findAll()); 
     List<Role> role = roleService.findAll(); 
     System.out.println(role.toString()); 
     return role; 
    } 

Modèle Rôle (commentaire @ManyToMany)

@Entity 
@JsonAutoDetect 
public class Role { 

    @Id 
    @GeneratedValue 
    private Integer id; 

    private String name; 

    /*@ManyToMany(fetch = FetchType.EAGER,mappedBy = "roles") 
    private List<User> users; 

    public List<User> getUsers() { 
     return users; 
    } 

    public void setUsers(List<User> users) { 
     this.users = users; 
    }*/ 

    public Integer getId() { 
     return id; 
    } 

    public void setId(Integer id) { 
     this.id = id; 
    } 

    public String getName() { 
     return name; 
    } 

    public void setName(String name) { 
     this.name = name; 
    } 

    public Role(String name) { 
     this.name = name; 
    } 
    public Role() { 
    } 

    @Override 
    public String toString() { 
     return "Role [id=" + id + ", name=" + name + "]"; 
    } 
} 

Modèle utilisateur

@Entity 
@JsonAutoDetect 
public class User { 

    @Id 
    @GeneratedValue 
    private Integer id; 

    private String name; 

    private String email; 

    private String password; 

    private boolean enabled; 

    @ManyToMany 
    @JoinTable 
    private List<Role> roles; 

    @OneToMany(mappedBy = "user", cascade = CascadeType.REMOVE) 
    private List<Blog> blogs; 

    public boolean isEnabled() { 
     return enabled; 
    } 

    public void setEnabled(boolean enabled) { 
     this.enabled = enabled; 
    } 

    public List<Blog> getBlogs() { 
     return blogs; 
    } 

    public void setBlogs(List<Blog> blogs) { 
     this.blogs = blogs; 
    } 

    public List<Role> getRoles() { 
     return roles; 
    } 

    public void setRoles(List<Role> roles) { 
     this.roles = roles; 
    } 

    public Integer getId() { 
     return id; 
    } 

    public void setId(Integer id) { 
     this.id = id; 
    } 

    public String getName() { 
     return name; 
    } 

    public void setName(String name) { 
     this.name = name; 
    } 

    public String getEmail() { 
     return email; 
    } 

    public void setEmail(String email) { 
     this.email = email; 
    } 

    public String getPassword() { 
     return password; 
    } 

    public void setPassword(String password) { 
     this.password = password; 
    } 

} 

service

@Service 
public class RoleService { 

    @Autowired 
    private RoleRepository roleRepository; 

    public List<Role> findAll(){ 
     return roleRepository.findAll(); 
    } 

JSP

<c:forEach items="${result}" var="item"> 
<a href="<spring:url value="/json2/${item.id}" />">json</a> 

</c:forEach> 

Répondre

0

Le problème est avec sérialisation des rôles de propriété de l'entité utilisateur. Lorsque vous chargez votre entité dans RoleService, puis renvoyez le résultat au contrôleur, la session de mise en veille prolongée est terminée. Vous n'êtes pas en mesure de le charger en dehors de la session d'hibernation.

Vous ne pouvez pas charger ces propriétés avec impatience aussi. Ensuite, il y aurait une chance de charger un grand arbre d'objets.

À mon avis pour résoudre votre proplem vous devez créer 3 services REST et 3 méthode de service normal qui chargerait des structures de données plates:

  1. /rôles/{id} - il charge le rôle unique (sans que les utilisateurs propriété)
  2. /rôles/{id}/utilisateurs - il charge tous les utilisateurs qui ont un rôle avec l'identifiant donné (sans propriété rôles)
  3. /users/{id}/rôles - il charge les rôles pour l'utilisateur avec l'identifiant donné

A dditionnellement, vous devez annoter vos propriétés de collection (rôles, utilisateurs) avec l'annotation @JsonIgnore pour les ignorer lors de la sérialisation vers json.