Hibernate实体管理器在查询前自动刷新,并将更改提交到事务中的数据库



我在Jboss AS 6.0.0 final上使用Hibernate 3.6.0和JPA 2。在我的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服务器一样,问题就消失了。我也试过用xa-datasource的mysql,但还是没有成功。。。

问题已解决。原因是mysql中的表默认使用MyISAM引擎,使用该引擎的表不支持事务。将表切换到innoDB可以使事情正常进行。希望这对任何人都有用,这样他们就不会像我那样浪费太多时间(

什么设置为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

在您声明实体管理器工厂之后。

最新更新