使用Spring REST服务的LazyInitializationException

时间:2013-11-11 12:45:25

标签: java spring hibernate rest spring-mvc

我有一个Spring应用程序与Hibernate相结合来编写一些我可以使用的服务。我没有视图,因为这些是来自手机的服务调用,它发送并获取JSON结果。

所以我有一个处理REST调用的Controller

@Controller
@RequestMapping(value = "/test")
public class TestController {
    @Autowired
    private TestService testService;
    …

    @RequestMapping(value = "/", method = RequestMethod.PUT)
    public ResponseEntity<Map<String, Object>> testMethod(
      @RequestHeader("userid") Integer userid, …) {
        User user = testService.getUserById(userid);
        List<Phone> phones = user.getPhones();
        phones.add(…);
        …
    }
}

如果我尝试访问Phones,我会收到org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.example.pojo.User.phones, no session or session was closed

我以这种方式注释了两个POJO类UserPhone,因此User是这种一对多关系的所有者:

@OneToMany(cascade = { CascadeType.ALL })
@JoinColumn(name = "USER_ID")
private List<Phone> phones;

@ManyToOne
@JoinColumn(name = "USER_ID", insertable = false, updatable = false, nullable = false)
private User user;

我的结构是服务 - &gt; ServiceImplementation和Dao - &gt; DaoImplementation。

ServiceImplementation方法getUserById(userid)已注释@Transactional

我该如何解决这个问题?我知道,在这个服务REST调用中,我总是需要获取手机列表。我读了......关于OpenSessionInView,但它似乎是使用视图的模式,我没有。

Hibernate.initialize(user.getPhones());放在List<Phone> phones = user.getPhones();前面不起作用。

我知道这是一个常见问题,但我不知道如何解决这个问题。

2 个答案:

答案 0 :(得分:1)

由于事务边界仅限于服务层,如果您尝试访问延迟加载的关系,它将为您提供您获得的异常,因为在您访问它时,事务已经结束,加载用户的持久性上下文关门了。您可以选择访问关系,或者将您的关系标记为急切加载到实体中,以便Hibernate在加载时自动加载它用户。

@OneToMany(cascade =  CascadeType.ALL, fetch = FetchType.EAGER)
@JoinColumn(name = "USER_ID")
private List<Phone> phones;

答案 1 :(得分:1)

基于此:

LazyInitializationException Within a @Transactional Method

设置注释驱动的交易:

<tx:annotation-driven />

然后注释你的方法@Transactional

只要您获得用户并在同一交易中访问其手机列表,您就可以使用延迟提取。即只有在响应中需要时才能获取手机列表。