J2EE - JPA - EJB3 - MDB方法中的事务

时间:2009-10-15 13:15:38

标签: java-ee ejb jboss5.x jta jboss-mdb

我在JBoss 5.1.0上部署了资源本地数据源(Oracle9i):

<datasources>
  <local-tx-datasource>
    <jndi-name>OracleDS</jndi-name>
    <connection-url>jdbc:oracle:thin:@IP_ADDRESS:1521:inv9i</connection-url>
    <driver-class>oracle.jdbc.driver.OracleDriver</driver-class>
    <user-name>***</user-name>
    <password>***</password>
    <exception-sorter-class-name>org.jboss.resource.adapter.jdbc.vendor.OracleExceptionSorter</exception-sorter-class-name>
    <metadata>
        <type-mapping>Oracle9i</type-mapping>
    </metadata>
  </local-tx-datasource>
</datasources>

持久性单位:

<persistence version="1.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_1_0.xsd">
    <persistence-unit name="myEJB" transaction-type="RESOURCE_LOCAL">
        <provider>org.hibernate.ejb.HibernatePersistence</provider>
        <non-jta-data-source>java:OracleDS</non-jta-data-source>
        <class>hr.bel.model.Instrument</class>
        <class>hr.bel.model.Order</class>
        <class>hr.bel.model.OrderAdditionalData</class>
        <class>hr.bel.model.OrderCondition</class>
        <class>hr.bel.model.Trade</class>
        <class>hr.bel.model.TradeAdditionalData</class>
        <class>hr.bel.model.Tradeticker</class>
        <properties>
            <property name="hibernate.dialect" value="org.hibernate.dialect.Oracle9iDialect"/>
            <property name="hibernate.hbm2ddl.auto" value="none" />
            <property name="hibernate.show_sql" value="true" />
        </properties>
    </persistence-unit>
</persistence>

在MDB中,当调用onMessage方法时,我正在尝试持久化bean并通过namedQuery获取该类型的最新5个bean:

@PersistenceContext
    EntityManager em = null;
    public void onMessage(MyMessage msg) {
        Map message = msg.getMessageTree(false);
        Instrument instrument = em.find(Instrument.class, 55);      

        Tradeticker tt = createTradeticker(message);
        tt.setInstrument(instrument);

        log.info("Persisting tradeticker: " + tt.getTradeType());               
        em.persist(tt);             
        log.info("Tradeticker persisted...");

        List<Tradeticker> last5 = em.createNamedQuery("getLast5").setParameter(1,instrument.getInstrumentId()).setMaxResults(5).getResultList();
        log.info("Persisted tradetickers size: " + last5.size());
    }

我的问题是没有任何错误的痕迹,但我的Oracle数据库中仍然没有任何持久对象。在大量消息之后,调用last5.size()返回0.日志非常干净。

我发现只有对MDB的限制是我必须在方法上使用REQUIRED或NOT_SUPPORTED事务属性。我的onMessage没有注释,所以它使用REQUIRED作为默认值。此外,我在MDB类上没有任何注释,因此bean应该使用容器管理的事务。

我做错了什么?

3 个答案:

答案 0 :(得分:2)

使用非jta数据源时,您不应该自己管理事务吗?也就是说,获取一个事务并自己提交数据?我自己把那种东西留给了JTA,但是当我正确地阅读this时,看起来你需要明确地提交。

答案 1 :(得分:2)

行。这就是我解决问题的方法,首先在persistence.xml中定义tx数据源,第二个定义jta模型和jta-datasource。

新数据源定义:

<datasources>
  <xa-datasource>
    <jndi-name>OracleDS</jndi-name>
    <isSameRM-override-value>false</isSameRM-override-value>
    <xa-datasource-class>oracle.jdbc.xa.client.OracleXADataSource</xa-datasource-class>
    <xa-datasource-property name="URL">jdbc:oracle:thin:@IP_ADDRESS:1521:inv9i</xa-datasource-property>
    <xa-datasource-property name="User">***</xa-datasource-property>
    <xa-datasource-property name="Password">***</xa-datasource-property>
    <exception-sorter-class-name>org.jboss.resource.adapter.jdbc.vendor.OracleExceptionSorter</exception-sorter-class-name>
    <no-tx-separate-pools/>
    <metadata>
      <type-mapping>Oracle9i</type-mapping>
    </metadata>
  </xa-datasource>

    JBoss的:服务=事务管理   

新的persistence.xml:

<persistence version="1.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_1_0.xsd">
    <persistence-unit name="myEJB" transaction-type="JTA">
        <provider>org.hibernate.ejb.HibernatePersistence</provider>
        <jta-data-source>java:OracleDS</jta-data-source>
        <class>hr.bel.model.Instrument</class>
        <class>hr.bel.model.Order</class>
        <class>hr.bel.model.OrderAdditionalData</class>
        <class>hr.bel.model.OrderCondition</class>
        <class>hr.bel.model.Trade</class>
        <class>hr.bel.model.TradeAdditionalData</class>
        <class>hr.bel.model.Tradeticker</class>

        <properties>
            <property name="hibernate.dialect" value="org.hibernate.dialect.Oracle9iDialect"/>
            <property name="hibernate.hbm2ddl.auto" value="none" />
            <property name="hibernate.show_sql" value="true" />
        </properties>
    </persistence-unit>
</persistence>

我的java代码是一样的,现在我的对象仍然存在!在与使用mysql dbms的同事讨论后,我们发现Oracle及其tx和no-tx数据源严格限制了数据源的使用方式和位置。 谢谢大家!

答案 2 :(得分:0)

顺便说一下:一个常见的模式是将业务逻辑放入SLSB并从MDB调用 - 允许其他逻辑使用。但是,对你的问题没有任何影响。

我希望默认的事务属性是Requried。我没有看到为什么这会失败的原因。

我会做这些事情:

1)。对业务逻辑进行try / catch。是否抛出任何异常?

2)。删除查询,我不明白为什么它应该失败,但让我们删除任何可能干扰插入的可能性。让我们依靠数据库。在使用几条消息后,使用命令行SQL语句或其他实用程序查看数据库中的内容。

3)。再次检查日志,是否出现错误?

相关问题