4

Jboss AS 6.0.0 final で JPA 2 で Hibernate 3.6.0 を使用しています。私のEJBには、エンティティ値を更新してそれに対してクエリを実行するメソッドがあります。メソッド全体が BMT トランザクションで実行されます。何かが失敗した場合、すべての変更はロールバックされ、DB にコミットされません。

データベースは mySql です。

JPA クエリを実行する前に、JPA は変更された状態を DB に自動フラッシュして、古いデータが返されないようにします。ただし、私の方法では、自動フラッシュが直接更新して変更を DB にコミットし、その後何か問題が発生したとしても、変更はロールバックされません。それで、私の設定に間違った設定があるのか​​、それともバグなのかを尋ねたいと思います.

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>

さらに調査したところ、フラッシュが発生するたびに、ダーティな変更が書き込まれ、DB に直接コミットされることがわかりました。flush() を削除すると、すべて正常に動作します。ただし、クエリの前にシステムによってトリガーされるフラッシュがあり、必要だと思います。

データベースは自動コミットされているようです。hibernate.connection.autocommitプロパティをに設定しようとしましfalseたが、問題が解決せず、仕様に違反しているという EJB 警告が表示されます。

更新:原因は mysql にあるはずです。mssqlサーバーに切り替えると、問題はなくなります。また、mysqlで試してみましたがxa-datasource、まだうまくいきません...

4

2 に答える 2

6

問題は解決しました。原因は、mysqlのテーブルがMyISAMデフォルトでエンジンを使用しており、このエンジンを使用するテーブルがトランザクションをサポートしていないためです。innoDB物事を機能させるためにテーブルを切り替える。これが誰にとっても役立つことを願っています。そうすれば、彼らは私ほど多くの時間を無駄にすることはありません。:(

于 2011-07-06T06:05:51.323 に答える
2

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 factory を宣言した後。

于 2011-06-30T15:14:03.833 に答える