Question

Je tente d'utiliser le gestionnaire de l'entité mise en veille prolongée avec MySQL et GlassFish. Je reçois l'erreur suivante lorsque vous tentez d'utiliser une source de données JTA:

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

Voici comment j'ai configuré mes 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="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>

Cependant, quand je configure une source de données non JTA, il fonctionne très bien

<?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>

C'est bien beau, mais je voudrais vraiment utiliser:

em.persist(myObject);

au lieu de:

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

Suis-je manque quelque chose avec la configuration de mise en veille prolongée, ou est-il même possible d'utiliser une source de données JTA?

Était-ce utile?

La solution

Il semble que pour votre configuration, les transactions gérées par le conteneur sont utilisées par défaut. Dans ce cas, vous devez définir un mode de synchronisation des transactions de sorte que la couche de persistance est notifiée (et peut mettre à jour le cache de niveau 2 par exemple). Vous devez donc définir manager_lookup_class propriété comme suit:

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

Aussi, vous devez marquer des méthodes commerciales qui ont accès à la couche de données « transactionnel ». Pour cela, vous devez les marquer avec @javax.ejb.TransactionAttribute(REQUIRED) (voir ici pour plus d'informations sur cette annotation).

Vous avez également la possibilité de passer à des transactions gérées par le bean. Vous pouvez le faire en disant:

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

Alors le haricot est responsable de début / fin de la transaction:

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();
    }
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top