4

我在 Jboss AS 6.0.0 final 上使用 Hibernate 3.6.0 和 JPA 2。在我的 EJB 中,有一种方法可以更新实体值并对其进行一些查询。整个方法在 BMT 事务中运行。如果有任何失败,所有更改都应该回滚,而不是提交给数据库。

数据库是 mySql。

在运行 JPA 查询之前,JPA 会自动将更改的状态刷新到 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();
            }       
        } 
}

持久性.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>

休眠.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.autocommitfalse但问题仍然存在,并提示违反规范的 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

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

于 2011-06-30T15:14:03.833 回答