2017-03-29 6 views
1

나는 Hibernate/JPA에 관한 책의 코드 샘플 인 (full source code) 코드 스 니펫에 대한 질의를 가지고있다.jpa/hibernate subselect 가져 오기에 대한 질의

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(); 
     } 
    } 

} 

이해가되지 않는 특정 부분이 하나입니다 : 그것은 부속 선택이 기능과 프리 페칭의 사용을 설명하기위한 것입니다

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에서 검색됨을 나타냅니다. 이것은 subselect prefetching이 작동하도록 의도 된 것입니까? ITEM 테이블에서 모두 ID을 검색하는 이유는 무엇입니까?

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

답변

2

부속의 프리 페 관련 아이를로드 할 때 로드 된 모든 부모에서 아이들이 초기화되도록 부모를로드하는 데 사용되는 원래 쿼리는 서브 쿼리로 사용되는 것을 의미한다 : 여기

Item 실체 한 가지. 부모를로드하는 쿼리는 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

감사합니다. 드라간. 하위 쿼리없이 동일한 결과가 쿼리에서 생성됩니까 (예 :'select * from BID')? – balteo

+0

@balteo 귀하의 구체적인 예를 들어, 모든 항목에 대한 입찰가가로드되고 항목이없는 입찰가가 있기 때문에 그렇게됩니다. 그러나 일반적인 경우 하위 쿼리가 분명히 필요합니다. –

+0

내가 정말로 이해하지 못하는 것은'where' 절없이 하위 쿼리를 사용하는 것입니다.'where' 절이없는 하위 쿼리의 요점은 무엇입니까 ?? – balteo