Диспетчер Hibernate Entity автоматически очищается перед запросом и фиксирует изменения в БД в транзакции - PullRequest
3 голосов
/ 29 июня 2011

Я использую Hibernate 3.6.0 с JPA 2 на Jboss AS 6.0.0 final. В моем EJB есть метод, который обновляет значения сущностей и делает некоторые запросы к нему. Весь метод выполняется в транзакции BMT. Если что-то не получается, все изменения должны быть отменены и не зафиксированы в БД.

База данных mySql.

Перед запуском запроса JPA JPA автоматически сбросит измененные состояния в DB, ​​чтобы предотвратить возвращение устаревших данных. Однако, в моем методе, автоматическая очистка напрямую обновляет и фиксирует изменения в БД, и даже после этого что-то пошло не так, изменения не являются откатом. Поэтому я хотел бы спросить, есть ли в моей настройке неправильная конфигурация или это ошибка или что-то в этом роде.

1007 * EJB *

@Stateless(mappedName = "MyManagementBean")
    @Local
    @TransactionManagement(TransactionManagementType.BEAN)


    public class MyManagement implements MyManagementLocal,MyManagementRemote {

        @PersistenceUnit(unitName="MyEjb") EntityManagerFactory emf;
        @Resource UserTransaction utx;
        @Resource SessionContext ctx;

        /**
         * Default constructor. 
         */
        public MyManagement () {
            // TODO Auto-generated constructor stub
        }

        public void dosomething(String id) throws Exception
        {

            try {
                utx.begin();    
                em = emf.createEntityManager();

                Myline line = em.find(Myline.class, id);

                line.setStatus("R");

            Stromg q += " from Myline as line ";             
                //auto flush apply here and directly committed to DB...
            Iterator iter = em.createQuery(q).getResultList().iterator();

                em.flush();
                utx.commit();// changes should only commit after this
            }
            catch (Exception e) {
                e.printStackTrace();
                if (utx != null) utx.rollback();
                throw e; // or display error message
            }
            finally {
                em.close();
            }       
        } 
}

persistence.xml

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.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_2_0.xsd">
    <persistence-unit name="MyEjb" transaction-type="JTA">
        <provider>org.hibernate.ejb.HibernatePersistence</provider>
        <jta-data-source>java:MyDS</jta-data-source>
        <class>com.quincy.entity.MyLine</class>

        <properties>
            <property name="hibernate.connection.defaultNChar" value="true"/>
            <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLMyISAMDialect"/>
            <property name="hibernate.ejb.cfgfile" value="META-INF/hibernate.cfg.xml"/>
        </properties>
    </persistence-unit>
</persistence>

hibernate.cfg.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
    <session-factory>


        <property name="transaction.manager_lookup_class">org.hibernate.transaction.JBossTransactionManagerLookup</property>


        <!-- Echo all executed SQL to stdout -->
        <property name="show_sql">true</property>       

        <property name="hibernate.max_fetch_depth">3</property>


    </session-factory>
</hibernate-configuration>

MySQL-ds.xml

<datasources>

<local-tx-datasource>
    <jndi-name>MyDS</jndi-name>
    <connection-url>jdbc:mysql://10.10.150.57:3306/myds</connection-url>
    <driver-class>com.mysql.jdbc.Driver</driver-class>
    <user-name>user</user-name>
    <password>pwd</password>
    <exception-sorter-class-name>org.jboss.resource.adapter.jdbc.vendor.MySQLExceptionSorter</exception-sorter-class-name>
    <metadata>
       <type-mapping>mySQL</type-mapping>
    </metadata>
  </local-tx-datasource>
</datasources>

После дальнейшего изучения я обнаружил, что при возникновении сброса грязные изменения записываются и фиксируются непосредственно в БД. Если я удаляю flush (), все работает нормально. Однако перед запросом происходит сброс системы, и я думаю, что это необходимо.

Мне кажется, что БД автоматически передается. Я попытался установить для свойства hibernate.connection.autocommit значение false, но проблема просто сохраняется, и выдается предупреждение EJB о нарушении спецификации.

ОБНОВЛЕНИЕ: Причина должна исходить из MySQL. Как будто я переключаюсь на mssql сервер, проблема исчезает. Я также пробовал mysql с xa-datasource, но все равно не повезло ...

Ответы [ 2 ]

5 голосов
/ 06 июля 2011

Проблема решена. Причина в том, что таблицы в mysql по умолчанию используют механизм MyISAM, а таблицы, использующие этот механизм, не поддерживают транзакции. Переключение таблиц на innoDB заставляет вещи работать. Надеюсь, это будет полезно для всех, так что они не будут тратить столько времени, как я. (

2 голосов
/ 30 июня 2011

Что установлено как entityManager FlushModeType

void setFlushMode(FlushModeType flushMode) 
Set the flush mode that applies to all objects contained in the persistence context.

Метод принимает перечисление, определенное здесь.

Enum Constant Summary

AUTO
       (Default) Flushing to occur at query execution.



COMMIT
       Flushing to occur at transaction commit.

Также попробуйте проверить следующее

@PersistenceContext(unitName="MyEJB") private EntityManager em

после объявления фабрики Entity Manager.

...