Pergunta

Estou tentando usar o Hibernate Entity Manager com MySQL e Glassfish. Estou recebendo o seguinte erro ao tentar usar um JTA DataSource:

Caused by: org.hibernate.HibernateException: The chosen transaction strategy requires access to the JTA TransactionManager
        at org.hibernate.impl.SessionFactoryImpl.<init>(SessionFactoryImpl.java:376)
        at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1367)
        at org.hibernate.cfg.AnnotationConfiguration.buildSessionFactory(AnnotationConfiguration.java:858)
        at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:733)
        ... 37 more

Aqui está como eu configurei minha persistência.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="myPU" transaction-type="JTA">
    <provider>org.hibernate.ejb.HibernatePersistence</provider>
    <jta-data-source>jdbc/mysql</jta-data-source>
    <class>com.my.shared.entity.MyFile</class>
    <class>com.my.shared.entity.MyRole</class>
    <class>com.my.shared.entity.MyUser</class>
    <exclude-unlisted-classes>true</exclude-unlisted-classes>
    <properties>
      <property name="hibernate.hbm2ddl.auto" value="create-drop"/>
      <property name="hibernate.show.sql" value="true" />
    </properties>

No entanto, quando eu configuro um conjunto de dados não JTA, funciona bem

<?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="myPU" transaction-type="JTA">
        <provider>org.hibernate.ejb.HibernatePersistence</provider>
        <non-jta-data-source>jdbc/mysql</non-jta-data-source>
        <class>com.my.shared.entity.MyFile</class>
        <class>com.my.shared.entity.MyRole</class>
        <class>com.my.shared.entity.MyUser</class>
        <exclude-unlisted-classes>true</exclude-unlisted-classes>
        <properties>
          <property name="hibernate.hbm2ddl.auto" value="create-drop"/>
          <property name="hibernate.show.sql" value="true" />
        </properties>
</persistence-unit>
</persistence>

Isso está tudo bem, mas eu realmente gostaria de usar:

em.persist(myObject);

ao invés de:

em.getTransaction().begin();
em.persist(myObject);
em.getTransaction().commit();

Estou perdendo alguma coisa com a configuração do Hibernate, ou é possível usar um conjunto de dados JTA?

Foi útil?

Solução

Parece que, para sua configuração, as transações gerenciadas por contêineres são usadas por padrão. Nesse caso, você precisa definir uma maneira de sincronização de transações para que a camada de persistência seja notificada (e pode atualizar o cache do segundo nível, por exemplo). Então você precisa definir manager_lookup_class propriedade como seguinte:

// For GlassFish:
hibernate.transaction.manager_lookup_class=org.hibernate.transaction.SunONETransactionManagerLookup
// For WebSpere:
hibernate.transaction.manager_lookup_class=org.hibernate.transaction.WebSphereExtendedJTATransactionLookup
// For JBoss:
hibernate.transaction.manager_lookup_class=org.hibernate.transaction.JBossTransactionManagerLookup
// For OpenEJB:
hibernate.transaction.manager_lookup_class=org.apache.openejb.hibernate.TransactionManagerLookup

Além disso, você deve marcar métodos de negócios que acessassem a camada de dados como "transacional". Para isso, você precisa marcá -los com @javax.ejb.TransactionAttribute(REQUIRED) (Vejo aqui Para mais informações sobre esta anotação).

Você também tem a opção de mudar para transações gerenciadas por feijão. Você pode fazer isso dizendo:

hibernate.transaction.factory_class=org.hibernate.transaction.JTATransactionFactory

Então o feijão é responsável por iniciar/encerrar a transação:

org.hibernate.Session session = ...;
org.hibernate.Transaction tx = null;
try {
    tx = session.beginTransaction();
    session.createQuery(...); // do some staff
    tx.commit();
} catch (HibernateException e)
{
    if (tx != null) {
        tx.rollback();
    }
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top