JPQLのdistinct
気になったのでちょっと調査。
部署(Department)と従業員(Employee)のエンティティが多対1のときで考えてみます。
JPQLでdistinctつけてDepartmentからEmployeeをfetch joinします。
JPQL
List<Department> list = entityManager
.createQuery(
"select distinct d from Department d left outer join fetch d.employees")
.getResultList();
すると、こんなSQLに変換されます。
SQL
select distinct department0_.deptno as deptno0_0_, employees1_.empno as empno1_1_, department0_.dname as dname0_0_, department0_.loc as loc0_0_, department0_.versionNo as versionNo0_0_, department0_.active as active0_0_, employees1_.ename as ename1_1_, employees1_.job as job1_1_, employees1_.mgr as mgr1_1_, employees1_.hiredate as hiredate1_1_, employees1_.sal as sal1_1_, employees1_.comm as comm1_1_, employees1_.tstamp as tstamp1_1_, employees1_.deptno as deptno1_1_, employees1_.city as city1_1_, employees1_.zip as zip1_1_, employees1_.deptno as deptno0__, employees1_.empno as empno0__ from Dept department0_ left outer join Emp employees1_ on department0_.deptno=employees1_.deptno
SQLにもdistinctがつくので、ResultSet上からの重複はなくなるわけですが、Departmentだけを見ると何度も同じものが登場します。
イメージとしてはこんな感じ。
deptno | empno |
---|---|
1 | 1 |
2 | 2 |
1 | 3 |
2 | 4 |
3 | 5 |
なのでこのままResultSetをDepartmentエンティティに変換すると重複するエンティティが存在することになっちゃいます。
Hibernateはどうしているかというと、distinctがついているときはちゃんとJavaのロジックで重複を取り除いていますね。
(QueryTranslatorImplのlistメソッド)