2010-03-01 11 views
8

J'essaie d'utiliser le gestionnaire d'entité hibernate avec mysql et glassfish. Je reçois l'erreur suivante lorsque vous tentez d'utiliser une source de données JTA:hibernate, mysql, glassfish v3, et 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é mon 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 un source de données non-jta, cela fonctionne 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> 

Tout cela est bien un d bien, 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 un Source de données JTA?

Répondre

11

Il semble que pour votre configuration, les transactions gérées par conteneur sont utilisées par défaut. Dans ce cas, vous devez définir une méthode de synchronisation des transactions afin que la couche de persistance soit notifiée (et qu'elle puisse mettre à jour le cache de second niveau par exemple). Donc, vous devez définir la propriété manager_lookup_class 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 here pour plus d'informations sur cette annotation).

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

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

Ensuite, 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(); 
    } 
} 
+2

ok, alors j'ai ajouté à mon persistence.xml. Maintenant, il "persiste" sans erreur, mais il ne s'engage jamais dans la base de données. – KevMo

+0

@KevMo: Vous n'avez pas besoin de faire une déclaration transactionnelle comme 'em.getTransaction(). Begin();', car vous utilisez CMT. J'espère que vous avez marqué votre méthode de haricot avec '@ Transactional'? –

+0

Ops, désolé, vous n'utilisez pas Spring :) Suivez ma réponse alors. –