Hibernate Entity管理器在查询之前自动刷新并在事务中提交对DB的更改

时间:2011-06-29 07:12:07

标签: hibernate transactions jpa-2.0 entitymanager hibernate-entitymanager

我在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(),一切正常。但是,在查询之前有系统触发的刷新,我认为这是必要的。

在我看来,db是自动提交的。我试图将属性hibernate.connection.autocommit设置为false,但问题仍然存在,并且提示违反规范的EJB警告。

更新:原因应该来自mysql。好像我切换到mssql服务器,问题就消失了。我也用xa-datasource尝试了mysql,但仍然没有运气......

2 个答案:

答案 0 :(得分:5)

问题已解决。 原因是mysql中的表默认使用MyISAM引擎,而使用此引擎的表不支持事务。 将表格切换为innoDB可以使事情有效。 希望这对任何人都有用,所以他们不会浪费我那么多的时间。 :(

答案 1 :(得分: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

宣布实体经理工厂后。