在处理通过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而不是对象。但是,这需要定义新类,随后的数据库更新可能会变得很麻烦......
有关如何轻松管理此问题的任何想法?
此外,似乎转换器或映射器并不是我真正需要的,因为我仍然需要在内存中加载完整的对象。
答案 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。