FlushModeType.COMMITでSELECTすると削除されたEntityが読めるのか?

Java EE勉強会で「FlushModeType.COMMITを指定してremovedなエンティティを読もうとしたら例外が起きるということが仕様書に書いてあったような...」と言ったのですが、言った後だんだん自信がなくなってきました。

ちょっとS2Hibernate-JPAを使って試してみました。

public class FlushModeTest extends S2TestCase {

  private EntityManager em;

  @Override
  protected void setUp() throws Exception {
    include("javaee5.dicon");
    include("s2hibernate-jpa.dicon");
  }

  public void testRemoveFindTx() throws Exception {
    final Employee emp = em.find(Employee.class, 7369L);
    em.remove(emp);
    try {
      em.find(Employee.class, 7369L);
      fail();
    } catch (EntityNotFoundException expected) {
    }
  }

  public void testRemoveFindWithCommitTypeTx() throws Exception {
    em.setFlushMode(FlushModeType.COMMIT);
    final Employee emp = em.find(Employee.class, 7369L);
    em.remove(emp);
    try {
      em.find(Employee.class, 7369L);
      fail();
    } catch (EntityNotFoundException expected) {
    }
  }

  public void testRemoveSelectTx() throws Exception {
    final Employee emp = em.find(Employee.class, 7369L);
    assertNotNull(emp);
    em.remove(emp);
    try {
      em.createQuery("select e from Emp e where empno = 7369")
          .getSingleResult();
      fail();
    } catch (NoResultException expected) {
    }
  }

  public void testRemoveSelectWithCommitTypeTx() throws Exception {
    em.setFlushMode(FlushModeType.COMMIT);
    final Employee emp = em.find(Employee.class, 7369L);
    assertNotNull(emp);
    em.remove(emp);
    final Employee emp2 = (Employee) em.createQuery(
        "select e from Emp e where empno = 7369").getSingleResult();
    assertNotNull(emp2);
  }

}

結論から言うと、私の言った内容は正しくなかったですorz。仕様書にそんなことかいてないし。

まぁそれはそれとして上記のテストコードからわかることは

  • removeした後そのEntityをfindした場合はFlushModeがAUTOでもCOMMITでも読み取れない。
  • removeした後JPQLでEntityをSELECTした場合、FlushModeがAUTOのときは読み取らないが、FlushModeがCOMMITのときは読み取れてしまう(読み取れちゃうことに気をつけろ!っていうのが勉強会での話でしたね)。

あと、findってEntityNotFoundExceptio投げることがあるんですね。でもこれってJPAの仕様外のような気のせいが...。findはEntityが存在しないときはnullを返すべきじゃない?