[英]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(...);
}
我的問題:
在“actory.getCurrentSession()。load(...);”行中,“factory”是什么類型,我該如何創建它? 是Hibernate.SessionFactory嗎? 還是Jboss或HTTP會話?
在“@PersistenceContext(name =”sample“)EntityManager em;” 什么是“名字”指的是什么? 我在論壇上找到了一個使用“unitName”而不是“name”的例子。 這行是如何我首先聲明我用來調用.persist()。find()等的EntityManager對象? (因此我的代碼不需要創建EntityManagerFactory)
我應該考慮研究和使用“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-unit
從persistence.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.