如何在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

查看:86
本文介绍了如何在JBoss AS 6,Hibernate 3.6,JPA,JTA和EJB3中使用容器管理事务(CMT)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图使用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); //成功工作
em.persist(newInstanceOfMyCustomEntity); //执行正确并生成一个ID
//但是实体在完成后不会保存到数据库中
}

persistence.xml的内容:

 <?xml version =1.0encoding = UTF-8 >?; 
< persistence version =1.0xmlns =http://java.sun.com/xml/ns/persistencexmlns:xsi =http://www.w3.org/2001/XMLSchema-实例xsi:schemaLocation =http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd\">
< persistence-unit name =myPersistanceUnitNametransaction-type =JTA>
< provider> org.hibernate.ejb.HibernatePersistence< / provider>
< jta-data-source> java:/ MySqlDS< / jta-data-source>
< class> my.custom.entity.Classes< / class>
<属性>
< property name =jboss.entity.manager.factory.jndi.namevalue =java:/ MyEntityManagerFactory/>
< property name =hibernate.transaction.factory_classvalue =org.hibernate.transaction.CMTTransactionFactory/>
< property name =hibernate.transaction.manager_lookup_classvalue =org.hibernate.transaction.JBossTransactionManagerLookup/>
< property name =hibernate.connection.autocommitvalue =false/>
< property name =hibernate.current_session_context_classvalue =jta/>
< / properties>
< / persistence-unit>
< /余辉>

Hibernate EntityManager文档对如何实现CMT的描述非常有限:






我们将CMT和EJB3容器使用的实体管理器/事务管理习惯简化为:
// CMT习惯用法注入
@PersistenceContext(name =sample)EntityManager em;




这个 jboss.org文章说:




使用EJB / CMT进行事务划分

我们的目标确实是从数据访问代码中删除任何事务分界代码:

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

/ /做一些工作
factory.getCurrentSession()。load(...);
factory.getCurrentSession()。persist(...);
}






我的问题: p>


  1. 在actory.getCurrentSession()。load(...);这一行中,factory是什么类型,我如何创建它?它是Hibernate.SessionFactory吗?或者一个Jboss或者HTTP会话?

  2. 在行@PersistenceContext(name =sample)EntityManager em;什么是名称?我在论坛上发现了一个使用unitName而不是name的例子。这行是如何我首先声明我用来调用.persist().find()等的EntityManager对象? (因此不需要创建EntityManagerFactory的代码) 我应该考虑研究和使用Java上下文和依赖注入(CDI)吗?


非常感谢任何帮助。请让我知道我应该提供哪些其他代码或配置文件




更新:如果我不使用EntityManagerFactory,而是使用@PersistenceContext来检索一个EntityManager,那么应该为我的会话bean(这个类正在回收+保存

$ b @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();



$ b $ p
$ b

如果这是正确的,那么persistence.xml需要什么?从我对doco和网页的所有阅读中,我不确定哪些可能是必需的:

 < property name = jboss.entity.manager.factory.jndi.namevalue =java:/ MyEntityManagerFactory/> 
< property name =hibernate.transaction.factory_classvalue =org.hibernate.transaction.CMTTransactionFactory/>
< property name =hibernate.transaction.manager_lookup_classvalue =org.hibernate.transaction.JBossTransactionManagerLookup/>
< property name =hibernate.connection.autocommitvalue =false/>
< property name =hibernate.current_session_context_classvalue =jta/>


解决方案

1)答案与您链接的文档:-)


在上面的示例中,您可以看到对SessionFactory的访问。你如何在代码中的任何地方访问工厂?同样,如果您运行在Java EE环境中,或者在JSE中使用嵌入式服务,那么您可以简单地从JNDI中查找它,Hibernate可以在启动时将其绑定。另一种解决方案是在启动后将其保留在全局静态单例中。



<2> 名称是对标签中指定名称的引用 persistence-unit 来自 persistence.xml 。在你的情况下,它是 myPersistanceUnitName 。 3)是的,如果你明白它不是要取代任何东西,它的目的是促进消费豆类(可能来自AS的资源)。


另外请注意,为了获得托管的EntityManager(带来好处),您不应该从AS获取EntityManagerFactory。你应该得到EM本身。就像你提到的,它就像这样:

  @PersistenceContext(name =myPersistanceUnitName)EntityManager em; 

它仅适用于由AS管理的东西,如Servlets,其他CDI bean,EJB ,...不知道Struts Action类是否会注入它: - )


I'm attempting to setup a web app using CMT. I've got it running standalone within Eclipse ok, and now I'm trying to get it working within Jboss AS 6, using Struts 1.0. I've chosen CMT because the doco I've read hints that it's the best and "least verbose to use". So seems like contempory/good-practice use of Hibernate 3.6.

I can load objects from a MySQL database with the following code extracts, but persisted objects are not being flushed/synchronised/saved to the database:

From within Struts 1.0 Action class:

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

'emf' is then passed to a method with my DAO class that is summarised below:

@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 
}

Contents of 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>

The Hibernate EntityManager documentation has a very limited description of how to achieve CMT:


Our entity manager/transaction management idiom for CMT and EJB3 container-use is reduced to this: //CMT idiom through injection @PersistenceContext(name="sample") EntityManager em;


And this jboss.org article says:


Transaction demarcation with EJB/CMT

Our goal really is to remove any transaction demarcation code from the data access code:

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

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


My questions:

  1. In the line "actory.getCurrentSession().load(...);", what type is "factory", and how do I create it? Is it Hibernate.SessionFactory? Or a Jboss or HTTP session?

  2. In the line "@PersistenceContext(name="sample") EntityManager em;" what is "name" referring to? I found an example on a forum of something using "unitName" instead of "name". Is this line how I first declare the EntityManager object that I use to call .persist() .find() etc? (and therefore my code that creates an EntityManagerFactory is not needed)

  3. Should I consider researching and using "Java Context and Dependency Injection" (CDI)?

Any help much appreciated. Please let me know what other bits of code or config files I should supply


Update:

If I don't use EntityManagerFactory, and retrieve an EntityManager instead using @PersistenceContext, then should something like this code for my "session bean" (the class retriving+saving entities on a per-user-session basis) be the way to do it?

@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();
}

If this is on the right track, what is needed in persistence.xml? From all my reading of doco and the web I'm not sure which of these might be required:

<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) The answer is in the same document you linked :-)

In the examples above you can see access to the SessionFactory. How do you get access to the factory everywhere in your code? Again, if you run in a Java EE environment, or use an embedded service in JSE, you could simply look it up from JNDI, where Hibernate can bind it on startup. Another solution is to keep it in a global static singleton after startup.

2) The name is a reference to the name specified in the tag persistence-unit from your persistence.xml. In your case, it's myPersistanceUnitName.

3) Yes, if you understand that it's not meant to replace anything, it's meant to facilitate the consumption of "beans" (which may be resources from the AS).

Also note that in order to get a managed EntityManager (with benefits), you should not get the EntityManagerFactory from the AS. You should get the EM itself. Like you mentioned, it's like this:

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

It will work only in things which are managed by the AS, like Servlets, other CDI beans, EJB, ... Not sure if Struts Action classes would get it injected :-)

这篇关于如何在JBoss AS 6,Hibernate 3.6,JPA,JTA和EJB3中使用容器管理事务(CMT)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆