如何在我的控制器中加载来自Hibernate / JPA的延迟获取项目 [英] How to load lazy fetched items from Hibernate/JPA in my controller

查看:120
本文介绍了如何在我的控制器中加载来自Hibernate / JPA的延迟获取项目的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个Person类:

  @Entity 
public class Person {

@Id
@GeneratedValue
私人长ID;

@ManyToMany(fetch = FetchType.LAZY)
private List< Role>角色;
// etc
}

通过多对多关系



在我的控制器中,我有

  @Controller 
@RequestMapping(/ person)
public class PersonController {
@Autowired
PersonRepository personRepository;

@RequestMapping(/ get)
public @ResponseBody Person getPerson(){
Person person = personRepository.findOne(1L);
return person;
}
}

PersonRepository就是这个代码,是根据本指南

  public interface PersonRepository扩展JpaRepository< Person,Long> {
}

然而,在这个控制器中,我实际上需要lazy-data 。如何触发它的加载?



试图访问它将会失败,并带有


未能延迟初始化角色集合:
no.dusken.momus.model.Person.roles,无法初始化代理 - no
Session


或其他例外,具体取决于我所尝试的内容。

我的 xml-description ,以防万一需要。

谢谢。

$ b $为了初始化它,你将不得不对lazy集合进行显式调用(通常的做法是调用 .size( )为此目的)。在Hibernate中有一个专门的方法( Hibernate.initialize()),但是JPA没有这个方法。当然,当会话仍然可用时,您必须确保调用已完成,因此使用 @Transactional 注释您的控制器方法。另一种方法是在Controller和Repository之间创建一个中间服务层,以便公开初始化懒惰集合的方法。



更新:



请注意,上述解决方案很简单,但会导致对数据库的两个不同查询(一个用于用户,另一个用于其角色)。如果您希望获得更好的性能,请将以下方法添加到您的Spring Data JPA存储库接口中:

  public interface PersonRepository扩展JpaRepository< Person ,Long> {

@Query(SELECT p FROM Person p JOIN FETCH p.roles WHERE p.id =(:id))
public Person findByIdAndFetchRolesEagerly(@Param(id)Long ID);




$ b这个方法将使用JPQL的提取加入子句,以便在一次往返数据库的过程中热切加载角色关联,并因此减轻所引起的性能损失通过上述解决方案中的两个不同的查询。

I have a Person class:

@Entity
public class Person {

    @Id
    @GeneratedValue
    private Long id;

    @ManyToMany(fetch = FetchType.LAZY)
    private List<Role> roles;
    // etc
}

With a many-to-many relation that is lazy.

In my controller I have

@Controller
@RequestMapping("/person")
public class PersonController {
    @Autowired
    PersonRepository personRepository;

    @RequestMapping("/get")
    public @ResponseBody Person getPerson() {
        Person person = personRepository.findOne(1L);
        return person;
    }
}

And the PersonRepository is just this code, written according to this guide

public interface PersonRepository extends JpaRepository<Person, Long> {
}

However, in this controller I actually need the lazy-data. How can I trigger its loading?

Trying to access it will fail with

failed to lazily initialize a collection of role: no.dusken.momus.model.Person.roles, could not initialize proxy - no Session

or other exceptions depending on what I try.

My xml-description, in case needed.

Thanks.

解决方案

You will have to make an explicit call on the lazy collection in order to initialize it (common practice is to call .size() for this purpose). In Hibernate there is a dedicated method for this (Hibernate.initialize()), but JPA has no equivalent of that. Of course you will have to make sure that the invocation is done, when the session is still available, so annotate your controller method with @Transactional. An alternative is to create an intermediate Service layer between the Controller and the Repository that could expose methods which initialize lazy collections.

Update:

Please note that the above solution is easy, but results in two distinct queries to the database (one for the user, another one for its roles). If you want to achieve better performace add the following method to your Spring Data JPA repository interface:

public interface PersonRepository extends JpaRepository<Person, Long> {

    @Query("SELECT p FROM Person p JOIN FETCH p.roles WHERE p.id = (:id)")
    public Person findByIdAndFetchRolesEagerly(@Param("id") Long id);

}

This method will use JPQL's fetch join clause to eagerly load the roles association in a single round-trip to the database, and will therefore mitigate the performance penalty incurred by the two distinct queries in the above solution.

这篇关于如何在我的控制器中加载来自Hibernate / JPA的延迟获取项目的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆