[英]How to get / initialize / unproxy data from session.load(E.class, id) in Hibernate?
[英]Hibernate: initialize vs unproxy
我在使用 ManyToMany 時遇到問題
@ManyToMany(cascade = { CascadeType.ALL }, fetch = FetchType.LAZY)
@JoinTable(
name = "PORTFOLIO_USER_PERMS",
joinColumns = { @JoinColumn(name = "USERNAME") },
inverseJoinColumns = { @JoinColumn(name = "PORTFOLIO_ID"), }
)
private List<Portfolio> sharedPortfolios = new ArrayList<>();
我有一個場景,其中一個 sharedPortfolios 一個元素是代理,另一個元素有一個代理屬性(由於一對一關系,actulay 是同一個對象)。 此列表通常返回到 Controller 方法,然后將其轉換為相應的 DTO。 正如您可能懷疑的那樣,具有代理對象的單個屬性會導致LazyInitializationException 。
這意味着在服務中,我需要遍歷列表中的每個元素,在將其傳遞給控制器之前,使用 Hibernate Utility: Hibernate.unproxy(...)查找可能是代理和取消代理的任何屬性。
我的問題:
1) Hibernate.initialize和Hibernate.unproxy 有什么區別?
初始化代理對象並不能解決問題。
2) 為什么其中一個元素是代理,而其他元素不是?
3)有什么比手動遍歷此列表和所有屬性並搜索代理對象更好的方法?
非常感謝。
此致。
要回答您的第一個問題,您可以查看這兩種方法的實現:
/**
* Unproxies a {@link HibernateProxy}. If the proxy is uninitialized, it automatically triggers an initialization.
* In case the supplied object is null or not a proxy, the object will be returned as-is.
*
* @param proxy the {@link HibernateProxy} to be unproxied
* @return the proxy's underlying implementation object, or the supplied object otherwise
*/
public static Object unproxy(Object proxy) {
if ( proxy instanceof HibernateProxy ) {
HibernateProxy hibernateProxy = (HibernateProxy) proxy;
LazyInitializer initializer = hibernateProxy.getHibernateLazyInitializer();
return initializer.getImplementation();
}
else {
return proxy;
}
}
和
/**
* Force initialization of a proxy or persistent collection.
* <p/>
* Note: This only ensures initialization of a proxy object or collection;
* it is not guaranteed that the elements INSIDE the collection will be initialized/materialized.
*
* @param proxy a persistable object, proxy, persistent collection or <tt>null</tt>
* @throws HibernateException if we can't initialize the proxy at this time, eg. the <tt>Session</tt> was closed
*/
public static void initialize(Object proxy) throws HibernateException {
if ( proxy == null ) {
return;
}
if ( proxy instanceof HibernateProxy ) {
( (HibernateProxy) proxy ).getHibernateLazyInitializer().initialize();
}
else if ( proxy instanceof PersistentCollection ) {
( (PersistentCollection) proxy ).forceInitialization();
}
else if ( proxy instanceof PersistentAttributeInterceptable ) {
final PersistentAttributeInterceptable interceptable = (PersistentAttributeInterceptable) proxy;
final PersistentAttributeInterceptor interceptor = interceptable.$$_hibernate_getInterceptor();
if ( interceptor instanceof EnhancementAsProxyLazinessInterceptor ) {
( (EnhancementAsProxyLazinessInterceptor) interceptor ).forceInitialize( proxy, null );
}
}
}
對於實體代理( HibernateProxy
)的實例,這兩種方法本質上是相同的,唯一的區別是unproxy
返回未經代理的實體。 從我到目前為止的測試來看,無論您使用返回值還是原始引用,都沒有區別。
initialize
也適用於持久集合( PersistentCollection
)。 當您需要初始化 ToMany-Relation 時,就像在您的問題中一樣,您將需要使用此方法。
初始化代理對象並不能解決問題。
您需要初始化集合sharedPortfolios
,而不僅僅是包含集合的對象:
Hibernate.initialize(entity.sharedPortfolios)
或者,您可能希望JOIN FETCH
查詢中的關系或使用實體圖以避免事后初始化並避免額外的查詢。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.