2012-03-27 62 views
3

這是我對這個問題進行了很多研究後的第一篇文章。使用JSF轉換器時延遲加載異常(引用集合)

這個例子的Jboss 7.1下運行與接縫3.1與接縫管理持久化上下文

我使用實體bean一個轉換器時面臨的一個問題,經典failed to lazily initialize a collection, no session or session was closed: org.hibernate.LazyInitializationException: failed to lazily initialize a collection, no session or session was closed(焊料+持久+面)。目標是通過重用JPA模型保持100%面向對象。

在beans.xml中,org.jboss.seam.transaction.TransactionInterceptor被激活

實體bean:

@Entity 
public class Member implements Serializable { 

    @Id 
    @GeneratedValue 
    private Long id; 
    private String name; 
    private String email; 

    @Column(name = "phone_number") 
    private String phoneNumber; 

    @ManyToMany 
    private List<Statut> listeStatut = new ArrayList<Statut>(); 

    // getters, setters, hashcode, equals 
} 

@Entity 
public class Statut implements Serializable { 

    @Id 
    @GeneratedValue 
    private Long id; 

    private String name; 

    @ManyToMany(mappedBy="listeStatut") 
    private List<Member> members = new ArrayList<Member>(); 

    // getters, setters, hashcode, equals 
} 

JSF頁面:

<h:form> 
    <h:selectManyCheckbox id="stat" value="#{memberModif.member.listeStatut}"> 
     <f:converter converterId="statutConverter"/> 
     <f:selectItems value="#{memberModif.statutsPossibles}" var="statut" itemValue="#{statut}" itemLabel="#{statut.name}" /> 
    </h:selectManyCheckbox> 


    <h:commandLink id="register" action="#{memberModif.modifier()}" value="Modifier"> 
     <f:param name="cid" value="#{javax.enterprise.context.conversation.id}"/> 
    </h:commandLink> 
</h:form> 

的支持bean(我試過ConversationScoped後SessionScoped - >同樣的問題)

@ConversationScoped 
@Named 
public class MemberModif implements Serializable { 

    private static final long serialVersionUID = -291355942822086126L; 

    @Inject 
    private Logger log; 

    @Inject 
    private EntityManager em; 

    @Inject Conversation conversation; 

    private Member member; 

    @SuppressWarnings("unused") 
    @PostConstruct 
    private void init() { 
     if (conversation.isTransient()) { 
      conversation.begin(); 
     } 
    } 

    public String modifier() { 
     em.merge(member); 
    } 

    public Member getMember() { 
     if (member == null) { 
      member = em.createQuery("from Member m where m.id=:id",Member.class).setParameter("id", new Long(0)).getSingleResult(); 
     } 
     return member; 
    } 

    public List<Statut> getStatutsPossibles() { 
     return em.createQuery("from Statut", Statut.class).getResultList(); 
    } 
} 

和轉換器(通過縫ObjectConverter強烈的啓發):

@FacesConverter("statutConverter") 
public class StatutConverter implements Converter, Serializable { 

    final private Map<String, Statut> converterMap = new HashMap<String, Statut>(); 
    final private Map<Statut, String> reverseConverterMap = new HashMap<Statut, String>(); 

    @Inject 
    private transient Conversation conversation; 

    private final transient Logger log = Logger.getLogger(StatutConverter.class); 

    private int incrementor = 1; 

    @Override 
    public Object getAsObject(FacesContext context, UIComponent component, String value) { 
     if (this.conversation.isTransient()) { 
      log.warn("Conversion attempted without a long running conversation"); 
     } 

     return this.converterMap.get(value); 
    } 

    @Override 
    public String getAsString(FacesContext context, UIComponent component, Object value) { 
     if (this.conversation.isTransient()) { 
      log.warn("Conversion attempted without a long running conversation"); 
     } 

     if (this.reverseConverterMap.containsKey(value)) { 
      return this.reverseConverterMap.get(value); 
     } else { 
      final String incrementorStringValue = String.valueOf(this.incrementor++); 
      this.converterMap.put(incrementorStringValue, (Statut)value); 
      this.reverseConverterMap.put((Statut)value, incrementorStringValue); 
      return incrementorStringValue; 
     } 
    } 
} 

請注意,我把這個轉換器在這裏,以避免您在搜索過網縫實現,但它與使用<s:objectConverter/>標籤而不是<f:converter converterId="statutConverter"/>

任何幫助將受到歡迎。

+0

<f:attribute name="collectionType" value="java.util.ArrayList" />; ,這一切看起來好像變流器訪問採集前的交易已經被關閉。你確定在這一點上你有交易嗎?注入的EntityManager的範圍是什麼? – 2012-03-27 14:34:49

回答

1

您應該訪問同一事務中的對象。如果你確定你已經這樣做了,你可以通過在上下文中查找而不是注入來獲取entitymanager。我有一個類似的問題,這種解決方式。當您第一次參考時,您也可以初始化交易中的集合。

Hibernate.initialize(yourCollection);