hibernate, mysql, glassfish v3 и источник данных JTA - PullRequest
8 голосов
/ 02 марта 2010

Я пытаюсь использовать hibernate-менеджер сущностей с mysql и glassfish. Я получаю следующую ошибку при попытке использовать источник данных 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

Вот как я настроил свой файл 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>

Однако, когда я настраиваю источник данных не-jta, он работает нормально

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

Это все хорошо, но я бы очень хотел использовать:

em.persist(myObject);

вместо:

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

Я что-то упустил в конфигурации гибернации, или вообще возможно использовать источник данных JTA?

1 Ответ

11 голосов
/ 02 марта 2010

Похоже, что для вашей конфигурации транзакции, управляемые контейнером, используются по умолчанию.В этом случае вам нужно определить способ синхронизации транзакций, чтобы уровень персистенции был уведомлен (и, например, может обновить кэш 2-го уровня).Поэтому вам необходимо определить свойство manager_lookup_class следующим образом:

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

Также вы должны пометить бизнес-методы, которые обращаются к уровню данных, как «транзакционные».Для этого вам нужно пометить их @javax.ejb.TransactionAttribute(REQUIRED) (см. здесь для получения дополнительной информации об этой аннотации).

У вас также есть возможность переключаться на транзакции, управляемые компонентом.Вы можете сделать это, сказав:

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

Тогда компонент отвечает за запуск / завершение транзакции:

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