处理'递归'实体从Hibernate中检索

时间:2015-12-04 16:52:43

标签: java spring hibernate spring-mvc jpa

在处理通过Hibernate检索源自数据库的潜在非常大的实体时,我想知道什么是最佳实践或常用方法。

考虑以下POJO:

class Movie implements Serializable {
    @Id 
    private long id;

    private String title;

    @ManyToMany(mappedBy="acted_movies")
    private Set<Person> cast;
}    

class Person implements Serializable {
    @Id
    private long id;

    private String name;

    @ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    @JoinTable(name = "Person_Movie_Actor", 
         joinColumns = { @JoinColumn(name = "person_id") }, 
         inverseJoinColumns = { @JoinColumn(name = "movie_id") })
    private Set<Movie> acted_movies;
}

从数据库中检索信息的过程如下:

@Autowired
private SessionFactory sessionFactory;

protected Session getSession() {
    return sessionFactory.getCurrentSession();
}

public Movie findById(long id) {
    Criteria criteria = getSession().createCriteria(Movie.class);
    criteria.add(Restrictions.eq("id", id));
    return (Movie) criteria.uniqueResult();
}

由于其属性的递归性质,我担心返回对象的大小:电影有一组演员,每个人都参与过电影,等等......

当然,我可以编写自己的自定义SQL查询,这样我只返回相关人员的ID而不是对象。但是,这需要定义新类,随后的数据库更新可能会变得很麻烦......

有关如何轻松管理此问题的任何想法?

此外,似乎转换器或映射器并不是我真正需要的,因为我仍然需要在内存中加载完整的对象。

2 个答案:

答案 0 :(得分:0)

您只能获取ID而无需创建任何其他类。

以下是获取电影人物ID的方法。

//em is entity manager
TypedQuery<Long> query = em.createQuery(
  "SELECT m.cast.id FROM Movie AS m where m.id=:movieId", Long.class);
query.setParameter("movieId",1l);
List<Long> personIds = query.getResultList();

答案 1 :(得分:0)

这似乎是由Hibernate直接处理的。可以指定FetchType.LAZY作为用于加载实体的获取类型,这不会加载关系(OneToOne等)。

然后可以显式调用Hibernate.initialize(..)来显式加载关系。

值得注意的是,Hibernate.initialize(..)并非递归地侵入所有成员。有关详细信息,请参阅此SO article