关于 jpa/hibernate 子选择提取的询问
Interrogation about jpa/hibernate subselect fetching
我有一个关于代码片段 (full source code) 的问题,它是一本关于 Hibernate/JPA 的书的附带代码示例。
这是代码清单:
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
// )
}
这是为了演示使用 prefetching with subselects feature of hibernate 和将要执行的 SQL 查询。
以下注释:// select ID from ITEM
表示所有项目 ID 都是从数据库中检索的。这就是子选择预取的作用吗?为什么要从 ITEM
table 中检索所有 ID
?
这是 Item
实体:
@Entity
public class Item {
@OneToMany(mappedBy = "item")
@org.hibernate.annotations.Fetch(
org.hibernate.annotations.FetchMode.SUBSELECT
)
protected Set<Bid> bids = new HashSet<>();
// ...
}
Subselect prefetching 是指原来用于加载parents的查询在加载关联children时作为子查询使用,这样中的children全部加载parents是一次性初始化的。您要加载 parents 的查询是 select i from Item i
(您加载所有项目),因此它被用作出价的子查询(转换为仅投影项目 ID)。
如果您的原始查询是 select i from Item i where i.someProperty = :something
,加载出价时的子查询将是 select ID from ITEM where SOME_PROPERTY_COLUMN = :something
。
我有一个关于代码片段 (full source code) 的问题,它是一本关于 Hibernate/JPA 的书的附带代码示例。
这是代码清单:
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
// )
}
这是为了演示使用 prefetching with subselects feature of hibernate 和将要执行的 SQL 查询。
以下注释:// select ID from ITEM
表示所有项目 ID 都是从数据库中检索的。这就是子选择预取的作用吗?为什么要从 ITEM
table 中检索所有 ID
?
这是 Item
实体:
@Entity
public class Item {
@OneToMany(mappedBy = "item")
@org.hibernate.annotations.Fetch(
org.hibernate.annotations.FetchMode.SUBSELECT
)
protected Set<Bid> bids = new HashSet<>();
// ...
}
Subselect prefetching 是指原来用于加载parents的查询在加载关联children时作为子查询使用,这样中的children全部加载parents是一次性初始化的。您要加载 parents 的查询是 select i from Item i
(您加载所有项目),因此它被用作出价的子查询(转换为仅投影项目 ID)。
如果您的原始查询是 select i from Item i where i.someProperty = :something
,加载出价时的子查询将是 select ID from ITEM where SOME_PROPERTY_COLUMN = :something
。