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のときにバージョンチェックが行われているみたいです。