1:加Fetch=FetchType.Lazy沒用,這個(gè)只能緩解,但是使用的時(shí)候即one.many.iterator()的時(shí)候還是會(huì)發(fā)送N條select語句
2:加@Fetch(JOIN)也沒用,這個(gè)屬于Hibernate提供的注解, 調(diào)用entityManager.find()或者自定義createQuery(jpql),雖然會(huì)使用外連接,但是一旦調(diào)用one.many.iterator的時(shí)候 還是避免不了發(fā)送select語句,除非jpql里面避免實(shí)體的查詢,只查詢實(shí)體屬性值,即返回值是個(gè)Object[],這樣可避免,因?yàn)闆]有機(jī)會(huì)調(diào)用one.many.iterator方法,都是實(shí)體屬性值。
最終解決方法是: jpql調(diào)用left/right/inner join fetch語句,主要是加fetch,不加效果仍然一樣,這樣即可避免調(diào)用one.many.iterator時(shí)發(fā)送N條select語句,只有一條外連接語句,它會(huì)無視FetchType屬性Lazy還是eager。
示例: A---->B @oneToMany A1 B多
1 //示意代碼
2 public class A{
3 @OneToMany(cascade={CascadeType.All},fetch=FetchType.Lazy,mappedBy="a")
//mappedBy表示當(dāng)前實(shí)體不維護(hù)外鍵,外鍵在多的一方維護(hù),即保存B的時(shí)候會(huì)保存A,也可設(shè)置為允許為null
4 private Set<B> bSet;
5
6 }
7 @Test
8 public void test(){
9 //最常見方式
10 //第一種
11 A a = entityManager.find(A.class,1L);
12 a.bSet.iterator();//觸發(fā)N條select語句
13
14 //第二種
15 Query query = entityManager.createQuery(select a from A a );
16 List<A> aList = query.getResultList();
17 aList.get(0).bSet.iterator();//觸發(fā)N條select語句
18
19 //第三種
20 Query query = entityManager.createQuery(select a from A a left join a.bSet b where a.id=?1);
21 List<A> aList = query.getResultList();
22 aList.get(0).bSet.iterator();//觸發(fā)N條select語句
23
24 //第四種
25 Query query = entityManager.createQuery(select a.name,b.name from A a left join a.bSet b where a.id=?1);
26 List<Object[]> aList=query.getResultList(); //返回值是數(shù)組,即是a.name和b.name沒有地方觸發(fā)N條select語句
27
28 //第五種
29 Query query = entityManager.createQuery(select a,b.name,b.id from A a left join a.bSet b where a.id=?1);
30 List<Object[]> aList=query.getResultList(); //返回值是數(shù)組,即a實(shí)體和b.name,b.id
31 (A)(aList.get(0)[0]).bSet.iterator()//觸發(fā)N條select語句。
32
33 //第六種
34 Query query = entityManager.createQuery(select a from A a left join fetch a.bSet b where a.id=?1);
35 List<A> aList = query.getResultList();
36 aList.get(0).bSet.iterator();//不會(huì)觸發(fā)N條select語句
37 //這里比第五種只多加了個(gè)fetch,就不會(huì)出現(xiàn)N條select語句
38
39 }
2 public class A{
3 @OneToMany(cascade={CascadeType.All},fetch=FetchType.Lazy,mappedBy="a")
//mappedBy表示當(dāng)前實(shí)體不維護(hù)外鍵,外鍵在多的一方維護(hù),即保存B的時(shí)候會(huì)保存A,也可設(shè)置為允許為null
4 private Set<B> bSet;
5
6 }
7 @Test
8 public void test(){
9 //最常見方式
10 //第一種
11 A a = entityManager.find(A.class,1L);
12 a.bSet.iterator();//觸發(fā)N條select語句
13
14 //第二種
15 Query query = entityManager.createQuery(select a from A a );
16 List<A> aList = query.getResultList();
17 aList.get(0).bSet.iterator();//觸發(fā)N條select語句
18
19 //第三種
20 Query query = entityManager.createQuery(select a from A a left join a.bSet b where a.id=?1);
21 List<A> aList = query.getResultList();
22 aList.get(0).bSet.iterator();//觸發(fā)N條select語句
23
24 //第四種
25 Query query = entityManager.createQuery(select a.name,b.name from A a left join a.bSet b where a.id=?1);
26 List<Object[]> aList=query.getResultList(); //返回值是數(shù)組,即是a.name和b.name沒有地方觸發(fā)N條select語句
27
28 //第五種
29 Query query = entityManager.createQuery(select a,b.name,b.id from A a left join a.bSet b where a.id=?1);
30 List<Object[]> aList=query.getResultList(); //返回值是數(shù)組,即a實(shí)體和b.name,b.id
31 (A)(aList.get(0)[0]).bSet.iterator()//觸發(fā)N條select語句。
32
33 //第六種
34 Query query = entityManager.createQuery(select a from A a left join fetch a.bSet b where a.id=?1);
35 List<A> aList = query.getResultList();
36 aList.get(0).bSet.iterator();//不會(huì)觸發(fā)N條select語句
37 //這里比第五種只多加了個(gè)fetch,就不會(huì)出現(xiàn)N條select語句
38
39 }
理論上JPA實(shí)體只要映射好關(guān)系,A--->B--->C--->D....... 只需from A 即可查詢出B C D, 但這樣做會(huì)影響性能,因?yàn)閷?shí)際中我們可能只需要不同表的若干屬性,而不是全部,所以首先有了LAZY,但是它只能緩解,真正使用的時(shí)候還是會(huì)觸發(fā)N條select語句,所以我們又希望一條join語句搞定,一般情況下,只需要使用left/right/inner join 即可,不需要加fetch,前提是select后面跟的是實(shí)體屬性而不是實(shí)體,而一旦跟上實(shí)體,那么由該實(shí)體獲取多的一方數(shù)據(jù)時(shí),仍然會(huì)觸發(fā)N條select語句,這個(gè)時(shí)候就要強(qiáng)制加上xxxx join fetch即可避免。
所以想避免one.many.iterator獲取多的一方數(shù)據(jù)觸發(fā)N條select語句,那么只有兩種辦法
1: select 后面跟實(shí)體屬性,不要跟實(shí)體, 再使用join。
2: 如果select 后面一定要跟實(shí)體,那么使用xxxx join fetch,這樣即使one.many.iterator的時(shí)候也不會(huì)觸發(fā)N條select語句。