簡體   English   中英

如何在JBoss AS 6,Hibernate 3.6,JPA,JTA和EJB3中使用容器管理事務(CMT)

[英]How to use Container Managed Transaction (CMT) with JBoss AS 6, Hibernate 3.6, JPA, JTA and EJB3

我正在嘗試使用CMT設置網絡應用程序。 我已經讓它在Eclipse中獨立運行了,現在我正在嘗試使用Struts 1.0在Jboss AS 6中運行它。 我選擇了CMT,因為我讀過的doco暗示它是最好的和“使用最不詳細”。 所以看起來像Hibernate 3.6的現代/良好實踐使用。

我可以使用以下代碼提取從MySQL數據庫加載對象,但持久化對象不會被刷新/同步/保存到數據庫:

從Struts 1.0 Action類中:

InitialContext ctx = new InitialContext();   
EntityManagerFactory emf = (EntityManagerFactory)ctx.lookup("java:/MyEntityManagerFactory");

然后將'emf'傳遞給我的DAO類的方法,總結如下:

@PersistenceContext(unitName="purejetJPA") EntityManager em;
@TransactionAttribute(TransactionAttributeType.REQUIRED)
exampleMethodInMyCustomDAOClass() {
EntityManager em = emf.createEntityManager();
em.find(MyCustomEntity.class, 542);  // works successfully
em.persist(newInstanceOfMyCustomEntity);          // this executes ok and generates an ID
                                                  // however the entity is not saved to database upon completion 
}

persistence.xml的內容:

    <?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
    <persistence-unit name="myPersistanceUnitName" transaction-type="JTA">
        <provider>org.hibernate.ejb.HibernatePersistence</provider>
        <jta-data-source>java:/MySqlDS</jta-data-source>
                <class>my.custom.entity.Classes</class>
                <properties>
            <property name="jboss.entity.manager.factory.jndi.name" value="java:/MyEntityManagerFactory"/>
            <property name="hibernate.transaction.factory_class" value="org.hibernate.transaction.CMTTransactionFactory"/>
            <property name="hibernate.transaction.manager_lookup_class" value="org.hibernate.transaction.JBossTransactionManagerLookup"/>
            <property name="hibernate.connection.autocommit" value="false"/>
            <property name="hibernate.current_session_context_class" value="jta"/>
        </properties>   
    </persistence-unit>
</persistence>

Hibernate EntityManager文檔對如何實現CMT的描述非常有限:


我們用於CMT和EJB3容器使用的實體管理器/事務管理習慣用法簡化為:// CMT習語通過注入@PersistenceContext(name =“sample”)EntityManager em;


這篇jboss.org文章說:


使用EJB / CMT進行事務划分

我們的目標實際上是從數據訪問代碼中刪除任何事務划分代碼:

@TransactionAttribute(TransactionAttributeType.REQUIRED)
public void doSomeWork() {

// Do some work
factory.getCurrentSession().load(...);
factory.getCurrentSession().persist(...);
}

我的問題:

  1. 在“actory.getCurrentSession()。load(...);”行中,“factory”是什么類型,我該如何創建它? 是Hibernate.SessionFactory嗎? 還是Jboss或HTTP會話?

  2. 在“@PersistenceContext(name =”sample“)EntityManager em;” 什么是“名字”指的是什么? 我在論壇上找到了一個使用“unitName”而不是“name”的例子。 這行是如何我首先聲明我用來調用.persist()。find()等的EntityManager對象? (因此我的代碼不需要創建EntityManagerFactory)

  3. 我應該考慮研究和使用“Java上下文和依賴注入”(CDI)嗎?

任何幫助非常感謝。 請讓我知道我應該提供的其他代碼或配置文件


更新:

如果我不使用EntityManagerFactory,並使用@PersistenceContext檢索EntityManager,那么我的“會話bean”(基於每個用戶會話的類還原+保存實體)的代碼應該是這樣做的嗎?它?

@Stateful
@TransactionManagement(value=TransactionManagementType.BEAN)
public class X implements IX {

@PersistenceContext(unitName="MySQL", type=PersistenceContextType.EXTENDED)
private EntityManager em;

@Resource
private UserTransaction tx;

public void doStuff() {
   tx.begin();
   em.joinTransaction();
   em.find(myEntity);
   em.perrsist(myEntity);
   tx.commit();
}

如果這是正確的軌道,persistence.xml需要什么? 從我對doco和網絡的所有閱讀中,我不確定可能需要哪些內容:

<property name="jboss.entity.manager.factory.jndi.name" value="java:/MyEntityManagerFactory"/>
<property name="hibernate.transaction.factory_class" value="org.hibernate.transaction.CMTTransactionFactory"/>
<property name="hibernate.transaction.manager_lookup_class" value="org.hibernate.transaction.JBossTransactionManagerLookup"/>
<property name="hibernate.connection.autocommit" value="false"/>
<property name="hibernate.current_session_context_class" value="jta"/> 

1)答案在你鏈接的同一文件中:-)

在上面的示例中,您可以看到對SessionFactory的訪問。 如何在代碼中到處訪問工廠? 同樣,如果你在Java EE環境中運行,或者在JSE中使用嵌入式服務,你可以簡單地從JNDI查找它,Hibernate可以在啟動時綁定它。 另一種解決方案是在啟動后將其保持在全局靜態單例中。

2) name是在標記中指定的名稱的引用persistence-unitpersistence.xml 在你的情況下,它是myPersistanceUnitName

3)是的,如果您了解它並不意味着要更換任何東西,那就意味着促進“豆類”(可能是來自AS的資源)的消費。

另請注意,為了獲得托管的EntityManager(帶有好處),您不應該從AS獲取EntityManagerFactory。 你應該得到EM本身。 就像你提到的,它是這樣的:

@PersistenceContext(name="myPersistanceUnitName") EntityManager em;

它只適用於由AS管理的東西,比如Servlets,其他CDI bean,EJB,......不確定Struts Action類是否會注入它:-)

我也有這個問題。 我已將其縮小到使用@WebService並通過@PersistenceContext注入EntityManager時,entitymanager為null。

此外,如果我們將數據訪問委托給DAO並為DAO類添加@TransactionAttribute(TransactionAttributeType.MANDATORY) ,它將拋出javax.ejb.EJBTransactionRequiredException

不知道這是否是一個JBoss錯誤,它不會將帶有@WebService注釋的無狀態會話bean添加到容器管理的事務中。

暫無
暫無

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

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