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
、まだうまくいきません...