簡體   English   中英

bean屬性的SEAM JSF Lazy Init異常

[英]SEAM JSF Lazy Init Exception on bean property

我在SEAM(2.2.2)應用程序中遇到了惰性初始化異常的問題,我使用的是SEAM管理的持久性上下文(通過JPA),如此處的文檔所述

SEAM文檔參考。 9.3.1使用JPA的SEAM管理的持久性上下文

從而在我的GenericDAO類中使用@In注入實體管理器

場景:

我有一個對話范圍的Bean,它注入了當前登錄的用戶實體(會話范圍的),當我試圖通過頁面中的JSF(el)延遲加載一些其他用戶屬性時,似乎拋出了LIE。

堆棧跟蹤錯誤:

2012-12-24 15:30:34,661 SEVERE [facelets.viewhandler] (http-0.0.0.0-8080-3) Error Rendering View[/user/settings.xhtml]: javax.el.ELException: /user/settings.xhtml: org.hibernate.LazyInitializationException: could not initialize proxy - no Session

at com.webapp.entities.Client_$$_javassist_29.getLogoUrl

起初我以為對話可能已超時,但這是通過注銷用戶而不是拋出LIE來解決的。

所以現在我想也許是因為從會話作用域注入了用戶實體,而動作Bean是對話作用域,所以該對象以某種方式與實體管理器分離了嗎?

不幸的是,並非每次都拋出異常,所以我無法輕松地重現它(該應用程序處於活動狀態,所以我會在一段時間內獲得錯誤)

我知道我可以通過將用戶屬性設置為EAGERLY來解決此問題,但我想先深入了解這一點,並且寧願不要先加載所有實體

有關我的設置的更多詳細信息:

components.xml:

<persistence:managed-persistence-context name="entityManager"
    auto-create="true"
    persistence-unit-jndi-name="java:/EntityManagerFactories/appData">  
</persistence:managed-persistence-context>

persistence.xml

<persistence-unit name="AppDatabase">
    <provider>org.hibernate.ejb.HibernatePersistence</provider>
    <jta-data-source>java:/appDatasource</jta-data-source>
    <properties>
        <property name="hibernate.connection.datasource" value="java:/appDatasource"/>
        <property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect"/>
        <property name="jboss.entity.manager.factory.jndi.name" value="java:/EntityManagerFactories/appData"/>
        <property name="hibernate.cache.use_second_level_cache" value="false"/>
        <property name="hibernate.show_sql" value="false"/> 
    </properties>
</persistence-unit>

通用DAO

public abstract class GenericDAOBean<T>
    implements GenericDAO<T>, Serializable{

private static final long serialVersionUID = 1L;

private Class<T> entityBeanType;

@In private EntityManager em;

@SuppressWarnings("unchecked")
public GenericDAOBean() {
    this.entityBeanType = (Class<T>) ((ParameterizedType) getClass()
                            .getGenericSuperclass()).getActualTypeArguments()[0];
}

/**
 * Set the entity manager to use
 * 
 * @param em
 */
public void setEntityManager(EntityManager em) {
    this.em = em;
}

/**
 * Get the current seam entity manager
 * 
 * @return
 */
 protected EntityManager getEntityManager() {
 //Seam entity manager set this way as of version 2.2.0 
 //can't handle abstract classes and @In doesn't inject
 //into this as a parent class
 EntityManager entityManager = (EntityManager)Component.getInstance("entityManager");
 if (entityManager == null)
     throw new IllegalStateException("Seam EntityManager has not been set on "
     +getEntityBeanType().getClass().getName()+"DAO before usage!");
     return entityManager;
 }

//Further Generic method follow here which are removed for brevity
}

如果您從Action Bean獲取User實體,請嘗試使用Action Bean

用戶user = entityManger.find(User.class,User.getId());

這應該將其加載到擴展的持久性上下文中,因為它看起來像是分離的

發表評論后進行編輯

您當然不會在getter方法中執行此操作,只需在訪問該bean之前的任何方法中執行一次,它將連接到您的擴展PC,我會說在您的action bean的@Create方法中執行。 關於您的最后一個問題:是否曾經將其加載到受會話限制的Seam管理的持久性上下文中?

另外,您還應為實體管理器注入“ @In EntityManager entityManager”,因為這是您在application.xml中配置的托管持久性上下文。 並且,如果您的實體曾經在此對話中被加載到EPC中,那就足夠了。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM