3

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

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

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

我的结构是 Service -> ServiceImplementation 和 Dao -> DaoImplementation。

ServiceImplementation 方法getUserById(userid)是注解的@Transactional

我怎么解决这个问题?我知道,在这个服务 REST 调用中,我总是需要获取电话列表。我读了某事。关于 OpenSessionInView,但它似乎是一种使用视图的模式,我没有。

把 aHibernate.initialize(user.getPhones());放在前面是List<Phone> phones = user.getPhones();行不通的。

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

4

2 回答 2

1

基于此:

@Transactional 方法中的 LazyInitializationException

设置注释驱动的事务:

<tx:annotation-driven />

然后注释你的方法@Transactional

只要您在同一事务中获取用户并访问他们的电话列表,那么您就可以使用延迟提取。即仅在响应中需要时才获取电话列表。

于 2013-11-11T13:08:41.000 回答
1

由于事务边界仅限于服务层,如果您尝试访问延迟加载的关系,它会给您带来异常,因为当您访问它时,事务已经结束并且加载用户的持久性上下文已关闭。您可以选择通过访问关系在服务层中急切地加载它,或者在实体中将关系标记为急切加载,以便 Hibernate 在加载用户时自动加载它。

@OneToMany(cascade =  CascadeType.ALL, fetch = FetchType.EAGER)
@JoinColumn(name = "USER_ID")
private List<Phone> phones;
于 2013-11-11T12:52:22.763 回答