【问题标题】:'No active transaction' and 'Cannot use an EntityTransaction while using JTA' when persisting object in filter?在过滤器中持久化对象时,“无活动事务”和“使用 JTA 时无法使用 EntityTransaction”?
【发布时间】:2014-09-07 11:18:46
【问题描述】:

我想使用过滤器将所有请求记录到我的 Web 服务器。

起初我尝试了我在 EJB 和 Web 服务类中使用的常规方式。一旦我尝试坚持,我的程序就会失败。我可以查询(此处未显示):

@PersistenceContext(unitName = "ConsoleManagement")
protected EntityManager em;
...
private void someMethod(){
        Request userRequest = new Request();
        userRequest.setApikey(apikey);
        userRequest.setFormat(requestedFormat);
        userRequest.setMethod(method);
        userRequest.setRequestIp(ip);
        userRequest.setRequestUrl(requestUrl);
        em.persist(userRequest); // fails here
        em.flush();
}

错误:

[ERROR   ] SRVE0315E: An exception occurred: com.ibm.ws.webcontainer.webapp.WebAppErrorReport: javax.persistence.TransactionRequiredException: No active transaction for PuId=WebApi#WebApi.war#PersistenceUnitName
    at com.ibm.ws.jpa.management.JPATxEntityManager.getEMInvocationInfo(JPATxEntityManager.java:250)

据此我收集到(尽管找不到任何文档)过滤器不是容器管理的。

然后我尝试了以下两个:

@PersistenceContext(unitName = "ConsoleManagement")
protected EntityManager em;
...
private void someMethod(){
        Request userRequest = new Request();
        userRequest.setApikey(apikey);
        userRequest.setFormat(requestedFormat);
        userRequest.setMethod(method);
        userRequest.setRequestIp(ip);
        userRequest.setRequestUrl(requestUrl);
        em.getTransaction().begin(); // fails here
        em.persist(userRequest);
        em.flush();
        em.getTransaction().commit()
}


@PersistenceUnit(unitName = "ConsoleManagement")
EntityManagerFactory emf;

public void someMethod() {
    EntityManager em = emf.createEntityManager();
    em.getTransaction().begin(); // fails here
    em.persist(userRequest);
    em.flush();
    em.getTransaction().commit();
    em.close();
}

两种情况都出错:

[ERROR   ] SRVE0315E: An exception occurred: com.ibm.ws.webcontainer.webapp.WebAppErrorReport: java.lang.IllegalStateException: 
Exception Description: Cannot use an EntityTransaction while using JTA.

[编辑] 如果我通过 @PersistenceUnit 注入 EntityManagerFactory 并删除 em.getTransaction().begin(),我会得到一个不同的错误。

@PersistenceUnit(unitName = "ConsoleManagement")
EntityManagerFactory emf;

public void someMethod() {
    EntityManager em = emf.createEntityManager();
    //em.getTransaction().begin(); 
    em.persist(userRequest);
    em.flush(); // fails here now
    //em.getTransaction().commit();
    em.close();
}

错误:

[ERROR   ] SRVE0315E: An exception occurred: com.ibm.ws.webcontainer.webapp.WebAppErrorReport: javax.persistence.TransactionRequiredException: 
Exception Description: No externally managed transaction is currently active for this thread

我现在有点卡住了。

[编辑] 持久化单元:

<persistence-unit name="ConsoleManagement">
    <description>This unit manages user data including user information, user projects, and project api keys</description>
    <jta-data-source>jdbc/db2dbcpdb/develop</jta-data-source>
    <class>com.utoronto.websphere.jaxrs.entities.Project</class>
    <class>com.utoronto.websphere.jaxrs.entities.User</class>
    <class>com.utoronto.websphere.jaxrs.entities.Api</class>
    <class>com.utoronto.websphere.jaxrs.entities.Apikey</class>
    <class>com.utoronto.websphere.jaxrs.entities.Version</class>
    <class>com.utoronto.websphere.jaxrs.entities.Request</class>
    <exclude-unlisted-classes>true</exclude-unlisted-classes>
</persistence-unit>

【问题讨论】:

  • ConsoleManagement 是带有transaction-type="JTA" 的持久性单元吗?
  • jdbc/db2dbcpdb/develop 已设置。这样会自动吗?

标签: jakarta-ee jpa jta


【解决方案1】:

规范指出,如果未指定 transaction-type,则默认为 Java EE 环境中的 JTA。由于您使用的是容器管理的 EntityManager,因此您无法像在 Java SE 环境中一样开始/提交/回滚 EntityTransaction

您可以通过@Resource 注解访问UserTransaction

public class MyFilter implements Filter {
    @Resource
    UserTransaction utx;

    @PersistenceContext
    EntityManager em;

    private void doSomething() {
        // ...
        utx.begin();
        em.persist(foo);
        utx.commit();
    }
}

【讨论】:

  • 谢谢,它成功了。在这种情况下,为什么容器不管理事务?
  • @user2316667 这将发生在 EJB 容器中,但您正在从 servlet 过滤器访问事务。我建议您创建一个持久化 userRequest 的无状态 EJB,并将其注入您的 servlet 过滤器。
  • 所以 b/c 我已经将我的事务类型设置为 JTA,我不能使用 EntityTranscations,而且因为过滤器不是容器管理的,我也不能注入容器管理的 entitymanagers。所以没有胜利。那正确吗? edit 非常感谢您的建议。干净多了。
  • @user2316667 我需要阅读规范,看看是否可以让 Web 容器管理事务,但对我来说它看起来并不自然。使用 EJB 层,您可以使用 @TransactionManagement 注释在 BMT 或 CMT 之间进行选择,还可以避免并发问题 - 注入到 servlet 实例变量中的容器管理的 EntityManager 不是线程安全的。
猜你喜欢
  • 2015-05-12
  • 2012-06-10
  • 2020-11-22
  • 1970-01-01
  • 1970-01-01
  • 2016-07-18
  • 2014-07-01
  • 2014-06-11
  • 2017-02-17
相关资源
最近更新 更多