在我的web應用程序中,我有一個與Child具有OneToMany關係的對象。 當選擇我的對象我執行以下查詢:jpa兒童體型表現
from Object o
,然後我應打印的每個對象有多少孩子有
// Foreach
object.children.size()
假設對象有很多孩子(讓我們說30'000); 是否浪費資源調用size()或者ORM框架(在我的情況下是Hibernate)會在不加載所有子項的情況下處理這個問題?
在我的web應用程序中,我有一個與Child具有OneToMany關係的對象。 當選擇我的對象我執行以下查詢:jpa兒童體型表現
from Object o
,然後我應打印的每個對象有多少孩子有
// Foreach
object.children.size()
假設對象有很多孩子(讓我們說30'000); 是否浪費資源調用size()或者ORM框架(在我的情況下是Hibernate)會在不加載所有子項的情況下處理這個問題?
使用JPA(標準):
Entity.getCollection().size()
會觸發延遲加載來檢索所有的子集合 - 所以是的,它會相當緩慢,除非您需要對所有/大多數元素進行操作。注意:對於JPA的所有(理性)實現,這不會發出30,000個單獨的查詢 - 它將發出一個查詢,返回結果集中的30,000行。@OneToMany(fetch=FetchType.EAGER)
getNativeQUery()
甚至SQL)通過EntityManager.getQuery()/getTypedQuery()/getNamedQuery()
使用JPQL。這是非常簡單,具有高性能:int empSize = em.createQuery("SELECT SIZE(d.employees) FROM Department d") .getSingleResult();
OR ALTERNATIVELY
// Pre-compiled query placed against entity class for highest performance
@NamedQueries({
@NamedQuery(name="Department.EmployeeSize",
query="SELECT SIZE(d.employees) FROM Department"),
... // other named queries
})
@Entity
public class Department {
...
}
// Then to use the query:
int empSize = em.createNamedQuery("Department.EmployeeSize", Integer.class)
.getSingleResult();
您可以啓用2級緩存。JPA Caching Summary
靜態配置二級緩存:
Map propertiesMap = new HashMap(); // Valid values are ALL, NONE, ENABLE_SELECTIVE, DISABLE_SELECTIVE propertiesMap.add("javax.persistence.sharedCache.mode", "ENABLE_SELECTIVE"); EntityManagerFactory = Persistence.createEntityManagerFactory("myPUName", propertiesMap);
ALTERNATIVELY use persistence.xml:
<persistence-unit name="EmployeeService">
...
<shared-cache-mode>ENABLE_SELECTIVE</shared-cache-mode>
</persistence-unit>
然後標記哪些實體應在2級緩存自動緩存:
@Cacheable(true)
@Entity
public class Employee {
...
}
使用專有方法的一部分(例如休眠 「超懶」 的集合):
在您的JPA實現中啓用日誌消息並查看真正發送到數據庫的數據庫查詢是個好主意。在你的情況下,我會說ORM可能會懶惰地加載所有對象,所以它會非常低效。
Hibernate有一個特殊的功能,稱爲「額外懶惰」的集合,將完全按照你剛纔的建議。這意味着如果您在其中一個超懶集合上調用size()
,它將返回內存中的子數,如果該集合已經初始化的話,但是如果該集合尚未初始化,將會查詢數據庫count
。目的是避免初始化非常大的集合,直到絕對必要。其他例外的事情包括處理Collection.contains
/Map.containsKey
調用,Map.get
調用,List.get(int)
等調用。
爲了紀念集合作爲額外慵懶的註解,你會說@org.hibernate.annotations.LazyCollection(EXTRA)
那麼,如果我想讓每個對象都有多少個孩子,那麼你的解決方案是什麼? – ianaz
@ianaz做什麼你會用普通的SQL做什麼。例如,你可以編寫一個查詢,返回對象與計數,例如''來自Object o,(從child where parent.id = o.id)選擇count(*)。「)。它仍然效率低下,但比指望Java方面更好。或者,您可以將查詢拆分爲兩個查詢,一個從Object o讀取所有對象'',另一個按父級對所有孩子進行分組並返回計數,例如,按父級從子組中選擇count(*)。 id「'並處理它。 –
編輯:最後一個查詢應該是'「選擇parent.id,通過parent.id從子組中計數(*)」 –