Как использовать Управляемую Контейнером Транзакцию (CMT) с JBoss AS 6, Hibernate 3.6, JPA, JTA и EJB3 - PullRequest
4 голосов
/ 21 марта 2011

Я пытаюсь настроить веб-приложение, используя CMT. У меня он работает автономно в Eclipse, и теперь я пытаюсь заставить его работать в Jboss AS 6, используя Struts 1.0. Я выбрал CMT, потому что документ, который я прочитал, намекает на то, что он лучший и «наименее многословный в использовании». Так что похоже на современное / хорошее применение Hibernate 3.6.

Я могу загрузить объекты из базы данных MySQL со следующими выдержками кода, но сохраненные объекты не сбрасываются / синхронизируются / сохраняются в базе данных:

Изнутри Struts 1.0 Класс действия:

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 (...);" какой тип является "фабричным" и как его создать? Это Hibernate.SessionFactory? Или сеанс Jboss или HTTP?

  2. В строке "@PersistenceContext (name =" sample ") EntityManager em;" что означает «имя»? Я нашел на форуме пример чего-то, использующего «unitName» вместо «name». В этой строке я впервые объявляю объект EntityManager, который я использую для вызова .persist () .find () и т. Д.? (и, следовательно, мой код, который создает EntityManagerFactory, не нужен)

  3. Должен ли я рассмотреть возможность исследования и использования "внедрения контекста и зависимости Java" (CDI)?

Любая помощь высоко ценится. Пожалуйста, дайте мне знать, какие еще биты кода или конфигурационные файлы я должен предоставить


Обновление:

Если я не использую EntityManagerFactory и вместо этого извлекаю EntityManager, используя @PersistenceContext, то должен ли что-то вроде этого кода для моего "сессионного компонента" (получение класса + сохранение сущностей для каждого пользовательского сеанса) быть способ сделать это?

@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? Судя по всему, что я читал о документах и ​​Интернете, я не уверен, что из этого может потребоваться:

<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"/> 

Ответы [ 2 ]

1 голос
/ 21 марта 2011

1) Ответ находится в том же документе, на который вы ссылались :-)

В приведенных выше примерах вы можете видеть доступ к SessionFactory.Как вы получаете доступ к фабрике везде в вашем коде?Опять же, если вы работаете в среде Java EE или используете встроенный сервис в JSE, вы можете просто найти его в JNDI, где Hibernate может связать его при запуске.Другое решение - сохранить его в глобальном статическом синглтоне после запуска.

2) name является ссылкой на имя, указанное в теге persistence-unit из вашего persistence.xml.В вашем случае это myPersistanceUnitName.

3) Да, если вы понимаете, что это не предназначено для замены чего-либо, это должно облегчить потребление "бобов" (которые могут быть ресурсами из AS).

Также обратите внимание, что для получения управляемого EntityManager (с преимуществами) вы не должны получать EntityManagerFactory от AS.Вы должны получить EM непосредственно.Как вы упомянули, это выглядит так:

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

Это будет работать только в вещах, управляемых AS, таких как сервлеты, другие компоненты CDI, EJB, ... Не уверен, что классы Struts Action получатэто впрыснуло: -)

0 голосов
/ 24 марта 2011

У меня тоже есть эта проблема. Я сузил его до использования @WebService, и мы вводим EntityManager через @PersistenceContext, EntityManager равен нулю.

Также, если мы делегируем доступ к данным для DAO и добавим @TransactionAttribute(TransactionAttributeType.MANDATORY) для класса DAO, он выдаст javax.ejb.EJBTransactionRequiredException.

Интересно, если это ошибка JBoss, которая не добавляет сессионные компоненты без сохранения состояния, имеющие аннотации @WebService к транзакции, управляемой контейнером.

...