Spring Data Rest FetchType

时间:2015-10-11 17:50:14

标签: java spring rest

使用ManyToMany注释时,Rest响应有问题。 问题是这个答案:

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"])

没有ManyToMany注释(就像在Model类Role中一样)我响应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;
    }

模型角色(评论@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 + "]";
    }
}

模型用户

@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
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>

1 个答案:

答案 0 :(得分:0)

问题在于序列化用户实体的属性角色。在RoleService中加载实体然后将结果返回给控制器时,hibernate会话结束。你无法在hibernate会话之外加载它。

您也不能急切地加载这些属性。然后就有机会加载大型物体树。

在我看来,要解决你的问题,你必须创建3个REST服务和3个正常的服务方法来加载平面数据结构:

  1. / roles / {id} - 它加载单个角色(没有用户属性)
  2. / roles / {id} / users - 它加载具有给定id角色的所有用户(没有roles属性)
  3. / users / {id} / roles - 为具有给定ID的用户加载角色
  4. 另外,您必须使用注释@JsonIgnore注释您的集合属性(角色,用户),以便在序列化到json期间忽略它们。