J2EE - JPA - EJB3 - транзакции в методах MDB

У меня есть ресурс локальных данных (Oracle9i), развернутый в JBoss 5.1.0:

<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, я пытаюсь сохранить бин и получить последние 5 бинов этого типа через namedQuery:

@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 ответа

Решение

Не следует ли вам самостоятельно управлять транзакцией при работе с источником данных, отличным от jta? То есть получить транзакцию и зафиксировать данные самостоятельно? Я оставляю подобные вещи самому JTA, но когда я читаю это правильно, похоже, что в вашем случае вы должны совершать действия явно.

ХОРОШО. Вот как я решил проблему: сначала определите источник данных tx, затем определите модель jta и источник данных jta в файле persistence.xml.

Новое определение источника данных:

<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: Сервис = TransactionManager

new 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 наложил строгие ограничения на то, как и где будут использоваться источники данных. Спасибо вам всем!

Попутно: общий шаблон состоит в том, чтобы поместить бизнес-логику в SLSB и вызывать ее из вашего MDB - допускает другое использование логики. Не должно иметь никакого значения к вашей проблеме, хотя.

Я ожидаю, что атрибут транзакции по умолчанию будет обязательным. Я не вижу причины, по которой это должно провалиться.

Я бы сделал эти вещи:

1). Положите попытку / поймать вокруг бизнес-логики. Есть какие-то исключения?

2). Удалите запрос, я не могу понять, почему он не должен работать, но давайте удалим любую возможность, если он может помешать вставке. Давайте опираться на базу данных. Используйте оператор SQL командной строки или другую утилиту, чтобы увидеть, что находится в БД после прохождения нескольких сообщений.

3). Проверьте журналы снова, ошибка появляется где-нибудь?

Другие вопросы по тегам