4
回答
又是JPA , 我的问题咋这么多!! 请指点
华为云数据库免费试用   
public Teacher {
  //...
  @OneToMany(mappedBy = "teacher", cascade = CascadeType.ALL,
             orphanRemoval = true)
  private List<Student> students = new ArrayList<Student>();
  //...
}

现在, 通过 “SELECT t FROM Teacher t WHERE t.id = 1l”  得到 teacher 实例, students 延时加载。 我现在不想把全部的 students 拉出来, 只需要一部分。 我的做法如下, 但失败了, 所以想请教一下,大家是怎么做的。

----- 无奈的分割线  -------------------------------------------------------

 我的代码是这样的,通过 JPQL 查询得到需要的 students 列表, 然后 setStudents(students)。 结果抛出“ A collection with cascade="all-delete-orphan" was no longer referenced by the owning entity instance:” 异常。 搜索一番后,按照网上给的例子改掉了。改为

List<Student> students = store.find...;
for (Student stu : students) {
   teacher.getStudents().add(event);
}

不抛出异常了, 但问题又出现了。

a.  当事务提交后,遍历 students 的时候会抛出延时加载异常(因为出了事务, 即使我已经add了,也不行,不解)。

b.  网上给的示例代码在 Add 前先执行 teacher.getStudents().clear(),但也不行,这样不是把数据都删掉了么(我真试了, 真删了!!)。

怎么办? 再写个重复的业务Bean ?  又或者 Teacher 里面 在加一个 Transient 的 List<Students> ?   这样岂不是很痛苦么?  

----- 痛苦的 --------------------------------

举报
子木007
发帖于7年前 4回/1K+阅
共有4个答案 最后回答: 7年前

请各位赐教!!!        

严重缺乏实践,  首次尝试 JPA , 带来方便的同时也带来了痛苦!

我的经验是尽量不要使用延迟加载(出了事务范围)

只有像图片字段这种才需要特殊对待

我理解你的意思就是要取出teacher和一部分特定条件的students

这完全应该一次性的将所有相关的数据取出来,不然就算你把bean塞回去变成Managed状态,也是要多次访问数据库,效率反而低

--- 共有 2 条评论 ---
浪客Dandy你可以把持久层的方法参数做的灵活一些,比如一个方法既可以不取Students也可以按照条件取一部分students,通过JPQL和Criteria API完全可以实现 7年前 回复
子木007我也不喜欢 LAZY, 但觉得 EAGER 也不好的,每次find 的时候,不管你需要不要student 都查出来了, 有点儿浪费 7年前 回复

不知道你是想限制关联加载的集合吗?如果是这样的话,可以:

@OrderBy

@Where

@BatchSize

private List<Student> students = new ArrayList<Student>();

更灵活的做法是:

List<Student> stus = session.createFilter(teacher.students,"select u.name,u.des from Student as s") .setFirstResult(2).setMaxResults(5).list();

//或者 List<Student> stus = session.createFilter(teacher.students,"select * from Student") .setFirstResult(2).setMaxResults(5).list();

//或者 Integer count = ( (Integer) s.createFilter(teacher.students, "select count(*)" ).list().get() ).intValue()

前提是你的provider是hibernate。

--- 共有 3 条评论 ---
子木007@大东哥 : 呵 , 领导的考虑是,如果发现hibernate 不合适的时候,可以方便的换成其他实现 7年前 回复
大东哥那我就不清楚了,为什么只能用JPA接口?为了将来可以替换实现?JPA标准只是hibernate的一个子集。 7年前 回复
子木007虽然底层是Hibernate, 但我们只允许用 JPA 的接口。 还能有别的方式么? 7年前 回复

找到一个算是比较折中的方式吧.

不用 select t from Teacher , 改成 Select NEW Teacher(xx,xx) 这样查询出来的结果,没有什么 LAZY/EAGER 的烦恼了, 也可以直接 setStudents(students)。

 

顶部