J2EE - JPA - EJB3 - 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 并通过命名查询获取该类型的最新 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 应该使用容器管理的事务。
我做错了什么?
I have resource local datasource (Oracle9i) deployed at 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 unit:
<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>
Within an MDB, when onMessage method is invoked I'm trying to persist an bean and fetch latest 5 beans of that type via an 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());
}
My problem is that there is no any trace of an error but still there is no any persisted objects in my Oracle database. After great number of messages call last5.size()
returns 0. Log is perfectly clean.
Only restrictions for MDBs I found are I have to use REQUIRED or NOT_SUPPORTED transaction attribute on methods. My onMessage is not annotated so it uses REQUIRED as default. Also I have no any annotations on MDB class so bean should use container managed transaction.
What I'm doing wrong?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
使用非 jta 数据源时,您不应该自己管理事务吗?也就是拿到一个事务,自己提交数据?我把这类事情留给 JTA 自己,但是当我正确阅读 this 时,它看起来就像你的情况一样,你需要明确承诺。
Shouldn't you manage the transaction yourself when working with a non-jta data source? That is, get a transaction and commit the data yourself? I leave that kind of stuff to JTA myself, but when I read this correctly it looks like in your case you need to commit explicitely.
好的。这就是我解决问题的方法,首先定义 tx 数据源,第二定义 jta 模型和 persistence.xml 中的 jta 数据源。
新的数据源定义:
jboss:service=事务管理器
新的 persistence.xml:
我的 java 代码是相同的,现在我正在持久化我的对象!在与使用 mysql dbms 的同事讨论后,我们发现 Oracle 及其 tx 和 no-tx 数据源对数据源的使用方式和位置进行了严格的限制。
谢谢大家!
OK. This is how I solved problem, 1st define tx datasource, 2nd define jta model and jta-datasource in persistence.xml.
New datasource definition:
jboss:service=TransactionManager
new persistence.xml:
My java code is same and now I'm getting my object persisted! After discussion with my colleagues who use mysql dbms we figure that Oracle with its tx and no-tx datasources made strict restrictions on how and where datasources will be used.
Thank you all!
顺便说一句:一种常见的模式是将业务逻辑放入 SLSB 中并从 MDB 中调用它 - 允许逻辑的其他用途。不过应该对你的问题没有什么影响。
我希望默认事务属性是必需的。我看不出这会失败的原因。
我会做这些事情:
1)。对业务逻辑进行尝试/捕获。是否抛出任何异常?
2)。删除查询,我不明白为什么它会失败,但让我们消除它可能干扰插入的任何可能性。让我们依靠数据库。在几条消息通过后,使用命令行 SQL 语句或其他实用程序查看数据库中的内容。
3)。再次检查日志,是否有任何地方出现错误?
In passing: a common pattern is to put the business logic into a SLSB and call that from your MDB - allows for other use of the logic. Should make no difference to your problem though.
I would expect the default transaction attribute to be Requried. I don't see a reason why this should fail.
I would do these things:
1). Put a try/catch around the business logic. Are any exceptions thrown?
2). Remove the query, I can't see why it should be failing, but lets remove any possibility taht it might be interfering with the insertion. Let's rely on the database. Use a command-line SQL statement or other utility to see what's in the DB after a few messages have gone through.
3). Check the logs again, is an error appearing anywhere?