我有一个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类User
和Phone
,因此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();
前面不起作用。
我知道这是一个常见问题,但我不知道如何解决这个问题。
答案 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
只要您获得用户并在同一交易中访问其手机列表,您就可以使用延迟提取。即只有在响应中需要时才能获取手机列表。