【问题标题】:Using Nativequery to delete/update records in JTA使用 Nativequery 删除/更新 JTA 中的记录
【发布时间】:2015-07-22 15:08:51
【问题描述】:

我一度陷入非常艰难的境地。

问题是:我必须使用 NativeQuery 来删除和/或更新 JTA 上下文 (EJB) 中的一些数据库记录。

我的 JPA persistence.xml 看起来像:

<persistence-unit name="OzsscJPANBPU" transaction-type="JTA">
    <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
    <jta-data-source>jdbc/postgres_ozssc</jta-data-source>
    <mapping-file>com/longz/ozssc/model/PostcodeEntity.xml</mapping-file>
    <class>com.longz.ozssc.model.CustomerEntity</class>
 ......

如果我以这种方式使用删除语句:

@Override
public void remove(SmsdOutboxEntity toberemoved){
    em.createNativeQuery("Delete from outbox where \"ID\" = " + toberemoved.getId()).executeUpdate();

TransactionRequiredException 抛出:

root cause

javax.persistence.TransactionRequiredException: 
Exception Description: No transaction is currently active

这样不存在交易。

如果我们手动使用事务:

@Override
public void remove(SmsdOutboxEntity toberemoved){
    em.getTransaction().begin();
    em.createNativeQuery("Delete from outbox where \"ID\" = " + toberemoved.getId()).executeUpdate();
    /*em.flush();*/
    em.getTransaction().commit();

抛出 IllegalStateException:

root cause

javax.ejb.EJBException: EJB Exception: ; nested exception is: 
java.lang.IllegalStateException: The method public abstract javax.persistence.EntityTransaction javax.persistence.EntityManager.getTransaction() cannot be invoked in the context of a JTA EntityManager.

看来我不能手动使用事务,因为 JTA 会自己管理事务。

所以我的问题是:如何使用 Native Query 删除/更新 JTA 托管上下文中的记录?

请指教。

【问题讨论】:

  • 您应该首先查看查询中的“ID”。为什么将列名放在引号中?您是否尝试过直接对您的数据库运行此查询?它是否达到了您的预期?
  • 第二件事:你提交的代码不足。为您的实体和 EJB 提供代码。您提交的代码可能还有其他问题,但根据您提供的代码很难说。
  • 第三件事:我强烈建议您重新考虑删除实体的方法。它会给你带来麻烦。除非您确切知道自己在做什么以及应该使用实体管理器的删除方法删除的后果是什么。更新也一样。
  • 我在查询中使用了“ID”,因为我的数据库表是区分大小写的,因为其他由 C++ 开发的应用程序也会访问该表。
  • 大部分工作由我的 C++ 应用程序完成。 My Java Application 仅用于处理异常记录和监控 C++ 应用程序的工作状态。所以删除逻辑是Java中唯一需要实现的逻辑。

标签: jpa transactions ejb jta


【解决方案1】:

对于 JTA,事务由容器提供,您不应该自己创建它。要在 JTA 中获取事务,您必须将其作为资源访问:

@Resource public UserTransaction utx;
@Resource public EntityManagerFactory factory;

@Override
public void remove(SmsdOutboxEntity toberemoved){
   EntityManager em = factory.createEntityManager();
try {
   em.createNativeQuery("Delete from outbox where \"ID\" = " + toberemoved.getId()).executeUpdate();
   utx.commit();

catch (RuntimeException e) {
    if (utx != null) utx.rollback();
    throw e; // or display error message
}
finally {
    em.close();
}

如果你想省略你自己提交/回滚事务的部分,你需要让你的事务由像 EJB3 这样的容器管理。为此,您可以使用无状态/有状态 ejb bean。

更新:

对于 WebLogic,请尝试使用其用户 weblogic.transaction.UserTransaction 而不是 javax.transaction.UserTransaction。正如文档所说:

此接口定义了特定于 WebLogic 的扩展 javax.transaction.UserTransaction.

【讨论】:

  • 我会测试你的建议并尽快回复。
  • 我测试了这个更新,它在我的情况下不起作用,Weblogic 12C 拒绝部署与 Weblogic 容器冲突的用户定义事务。我需要更多的研究来看看我们能做些什么。如果你有更好的主意,请告诉我。赞赏...
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-28
  • 1970-01-01
  • 2015-02-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多