Merge実行時にSELECT文が実行されるのか?
試してみました。
使ったEntityはS2Hibernate-JPAのテストケースで使っているEmployeeクラスです。ただ、バージョンチェックがいつ行われるかの確認を行いたかったのでversionNoフィールドを追加して@Versionをつけました。(Empテーブルに対応するカラムも追加しました。)
public class MergeTest extends S2TestCase { private UserTransaction utx; private EntityManager em; @Override protected void setUp() throws Exception { include("javaee5.dicon"); include("s2hibernate-jpa.dicon"); } public void test() throws Exception { System.out.println("\n## FIND ##"); Employee emp = em.find(Employee.class, 7369L); emp.setEname("hoge"); utx.begin(); System.out.println("\n## MERGE ##"); em.merge(emp); System.out.println("\n## COMMIT ##"); utx.commit(); } public void testVersionCheck() throws Exception { Employee emp = em.find(Employee.class, 7369L); emp.setEname("hoge"); utx.begin(); em.merge(emp); em.flush(); try { em.merge(emp); fail(); } catch (OptimisticLockException expected) { } utx.rollback(); } }
上記のtestメソッドを実行したときのSQLはこんな風になりました。mergeでSELECT文が発行されていることがわかります。
## FIND ## Hibernate: select employee0_.empno as empno0_1_, employee0_.ename as ename0_1_, employee0_.job as job0_1_, employee0_.mgr as mgr0_1_, employee0_.hiredate as hiredate0_1_, employee0_.sal as sal0_1_, employee0_.comm as comm0_1_, employee0_.tstamp as tstamp0_1_, employee0_.deptno as deptno0_1_, employee0_.versionNo as versionNo0_1_, department1_.deptno as deptno1_0_, department1_.dname as dname1_0_, department1_.loc as loc1_0_, department1_.versionNo as versionNo1_0_, department1_.active as active1_0_ from Emp employee0_ left outer join Dept department1_ on employee0_.deptno=department1_.deptno where employee0_.empno=? ## MERGE ## Hibernate: select employee0_.empno as empno0_0_, employee0_.ename as ename0_0_, employee0_.job as job0_0_, employee0_.mgr as mgr0_0_, employee0_.hiredate as hiredate0_0_, employee0_.sal as sal0_0_, employee0_.comm as comm0_0_, employee0_.tstamp as tstamp0_0_, employee0_.deptno as deptno0_0_, employee0_.versionNo as versionNo0_0_ from Emp employee0_ where employee0_.empno=? Hibernate: select department0_.deptno as deptno1_0_, department0_.dname as dname1_0_, department0_.loc as loc1_0_, department0_.versionNo as versionNo1_0_, department0_.active as active1_0_ from Dept department0_ where department0_.deptno=? ## COMMIT ## Hibernate: update Emp set ename=?, job=?, mgr=?, hiredate=?, sal=?, comm=?, tstamp=?, deptno=?, versionNo=? where empno=? and versionNo=?
testVersionCheckメソッドでは一度DBのversionNoを更新してから古いversionNoを持つEmployeeをmergeしています。commitのときではなくmergeのときにバージョンチェックが行われているみたいです。