2017-03-29 10 views
1

私は、コードスニペット(full source code)についての質問があります。これは、Hibernate/JPAに関する書籍の付属コードサンプルです。ここでjpa/hibernateサブセレクトフェッチに関する質問

は、コードリストである:

public class Subselect extends JPATest { 

    @Override 
    public void configurePersistenceUnit() throws Exception { 
     configurePersistenceUnit("FetchingSubselectPU"); 
    } 

    public FetchTestData storeTestData() throws Exception { 
     UserTransaction tx = TM.getUserTransaction(); 
     tx.begin(); 
     EntityManager em = JPA.createEntityManager(); 

     Long[] itemIds = new Long[3]; 
     Long[] userIds = new Long[3]; 

     User johndoe = new User("johndoe"); 
     em.persist(johndoe); 
     userIds[0] = johndoe.getId(); 

     User janeroe = new User("janeroe"); 
     em.persist(janeroe); 
     userIds[1] = janeroe.getId(); 

     User robertdoe = new User("robertdoe"); 
     em.persist(robertdoe); 
     userIds[2] = robertdoe.getId(); 

     Item item = new Item("Item One", CalendarUtil.TOMORROW.getTime(), johndoe); 
     em.persist(item); 
     itemIds[0] = item.getId(); 
     for (int i = 1; i <= 3; i++) { 
      Bid bid = new Bid(item, robertdoe, new BigDecimal(9 + i)); 
      item.getBids().add(bid); 
      em.persist(bid); 
     } 

     item = new Item("Item Two", CalendarUtil.TOMORROW.getTime(), johndoe); 
     em.persist(item); 
     itemIds[1] = item.getId(); 
     for (int i = 1; i <= 1; i++) { 
      Bid bid = new Bid(item, janeroe, new BigDecimal(2 + i)); 
      item.getBids().add(bid); 
      em.persist(bid); 
     } 

     item = new Item("Item Three", CalendarUtil.AFTER_TOMORROW.getTime(), janeroe); 
     em.persist(item); 
     itemIds[2] = item.getId(); 
     for (int i = 1; i <= 1; i++) { 
      Bid bid = new Bid(item, johndoe, new BigDecimal(3 + i)); 
      item.getBids().add(bid); 
      em.persist(bid); 
     } 

     tx.commit(); 
     em.close(); 

     FetchTestData testData = new FetchTestData(); 
     testData.items = new TestData(itemIds); 
     testData.users = new TestData(userIds); 
     return testData; 
    } 

    @Test 
    public void fetchCollectionSubselect() throws Exception { 
     storeTestData(); 

     UserTransaction tx = TM.getUserTransaction(); 
     try { 
      tx.begin(); 
      EntityManager em = JPA.createEntityManager(); 

      List<Item> items = em.createQuery("select i from Item i").getResultList(); 
      // select * from ITEM 

      for (Item item : items) { 
       assertTrue(item.getBids().size() > 0); 
       // select * from BID where ITEM_ID in (
       // select ID from ITEM 
       //) 
      } 

      // The actual test 
      em.clear(); 
      items = em.createQuery("select i from Item i").getResultList(); 
      // Access should load all collections 
      assertTrue(items.iterator().next().getBids().size() > 0); 
      em.clear(); // Detach all 
      for (Item item : items) { 
       assertTrue(item.getBids().size() > 0); 
      } 

      tx.commit(); 
      em.close(); 
     } finally { 
      TM.rollback(); 
     } 
    } 

} 

私は理解していない特定の部分はこの1つである:

for (Item item : items) { 
    assertTrue(item.getBids().size() > 0); 
    // select * from BID where ITEM_ID in (
    // select ID from ITEM 
    //) 
} 

サブセレクトでプリフェッチの使用方法を示すためのものですを備えていますhibernateと実行されるSQLクエリーの両方

次のコメント:// select ID from ITEMは、すべてのアイテムIDがDBから取得されることを示します。これは、副選択プリフェッチが動作するためのものですか?なぜITEMテーブルからすべてIDを取得するのですか?ここで

Itemエンティティです:

@Entity 
public class Item { 
@OneToMany(mappedBy = "item") 
@org.hibernate.annotations.Fetch(
org.hibernate.annotations.FetchMode.SUBSELECT 
) 
protected Set<Bid> bids = new HashSet<>(); 
// ... 
} 

答えて

2

副選択のプリフェッチは、関連する子どもをロードするときロードされているすべての両親の子供たちががで初期化されるように、親をロードするために使用された元のクエリが、サブクエリとして使用されることを意味します1つ行く。親をロードするクエリはselect i from Item i(すべてのアイテムを読み込む)なので、入札用のサブクエリとして使用されます(アイテムのIDのみを投影するように変換されます)。

元のクエリがselect i from Item i where i.someProperty = :somethingの場合、入札単価を読み込むときのサブクエリはselect ID from ITEM where SOME_PROPERTY_COLUMN = :somethingになります。

+0

ありがとうDragan。サブクエリなしで同じ結果が得られるでしょうか(つまり、 'select * from BID')? – balteo

+0

@balteo具体的な例では、すべてのアイテムの入札がロードされ、アイテムのない入札はありません。しかし、一般的にサブクエリが明らかに必要です。 –

+0

私が実際に理解していないのは、 'where'句なしでサブクエリを使うことです。' where'句のないサブクエリのポイントは何ですか? – balteo