【问题标题】:EntityManager.persist() method hangingEntityManager.persist() 方法挂起
【发布时间】:2014-02-18 22:55:13
【问题描述】:

不确定是否有人遇到过这个问题。我正在使用带有 EJB3.1 的 Jboss7.1 应用程序服务器和带有 Hibernate 实现的 JPA2.0。我正在使用后端 Oracle 11g 数据库。请看下面的代码。我正在使用由 HTTP GET 请求驱动的 servlet 调用我的 EJB。

当我在下面的代码中注释掉context.setRollbackOnly() 时,我的网页会永远挂起,一段时间后我会低于堆栈跟踪(如果我调试,它需要我直到 persist() 方法,然后什么也没有)。

21:56:22,765 WARN [com.arjuna.ats.arjuna] (Transaction Reaper) ARJUNA012117: TransactionReaper::check timeout for TX 0:ffffc0a80005:57a36cd7:5303d0bf:30 in state RUN 21:56:22,767 WARN [com.arjuna.ats.arjuna](Transaction Reaper Worker 2)ARJUNA012095:中止操作 id 0:ffffc0a80005:57a36cd7:5303d0bf:30 在其中多个线程处于活动状态时被调用。 21:56:22,768 WARN [com.arjuna.ats.arjuna](事务收割工人 2)ARJUNA012108:CheckedAction::check - 原子动作 0:ffffc0a80005:57a36cd7:5303d0bf:30 中止,有 1 个线程处于活动状态! 21:56:23,266 WARN [com.arjuna.ats.arjuna](事务收割机)ARJUNA012117:TransactionReaper::检查 TX 0 的超时:ffffc0a80005:57a36cd7:5303d0bf:30 处于取消状态 21:56:23,767 WARN [com.arjuna.ats.arjuna](事务收割机)ARJUNA012117:TransactionReaper::check timeout for TX 0:ffffc0a80005:57a36cd7:5303d0bf:30 in state CANCEL_INTERRUPTED 21:56:23,768 WARN [com.arjuna.ats.arjuna] (Transaction Reaper) ARJUNA012120: TransactionReaper::check worker Thread[Transaction Reaper Worker 2,5,main] 在取消 TX 0:ffffc0a80005:57a36cd7 时没有响应中断: 5303d0bf:30 -- 工人标记为僵尸和 TX 计划标记为回滚 21:56:23,770 WARN [com.arjuna.ats.arjuna] (Transaction Reaper) ARJUNA012110: TransactionReaper::check 成功将 TX 0:ffffc0a80005:57a36cd7:5303d0bf:30 标记为仅回滚

context.setRollbackOnly() 未注释,然后页面加载,但后端表中没有记录。相同的代码间歇性地工作。我无法弄清楚它何时起作用的实际模式!有没有人可以点灯?

我的 EJB 代码如下 -

import javax.annotation.Resource;
import javax.annotation.security.DeclareRoles;
import javax.annotation.security.RolesAllowed;
import javax.ejb.Local;
import javax.ejb.SessionContext;
import javax.ejb.Stateless;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import javax.ejb.TransactionManagement;
import javax.ejb.TransactionManagementType;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;


@Stateless
@Local(DepartmentLocal.class)
@TransactionManagement(TransactionManagementType.CONTAINER)
@DeclareRoles({"Admin", "Guest"})
public class DepartmentBean{

@Resource
private SessionContext context;

@PersistenceContext(unitName="department-pu")
private EntityManager em;



@TransactionAttribute(TransactionAttributeType.REQUIRED)
@RolesAllowed({"Admin"})
public long addDepartment(Department dep){

    em.persist(dep);        

    //context.setRollbackOnly();
    return dep.getDepartmentId();
}

}

更新:

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name="DEPARTMENTS")
public class Department {
 @Id
 @Column(name="DEPARTMENT_ID")
 private long departmentId;

@Column(name="DEPARTMENT_NAME")
private String departmentName;

@Column(name="MANAGER_ID")
private long managerId;

@Column(name="LOCATION_ID")
private long locationId;

public long getDepartmentId() {
    return departmentId;
}

public void setDepartmentId(long departmentId) {
    this.departmentId = departmentId;
}

public String getDepartmentName() {
    return departmentName;
}

public void setDepartmentName(String departmentName) {
    this.departmentName = departmentName;
}

public long getManagerId() {
    return managerId;
}

public void setManagerId(long managerId) {
    this.managerId = managerId;
}

public long getLocationId() {
    return locationId;
}

public void setLocationId(long locationId) {
    this.locationId = locationId;
}


}

META-INF/persistence.xml

<?xml version="1.0" encoding="UTF-8"?>
<persistence 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_2_0.xsd"
version="2.0">
<persistence-unit name="department-pu" transaction-type="JTA">
    <provider>org.hibernate.ejb.HibernatePersistence</provider>
    <jta-data-source>java:jboss/datasources/OracleDS</jta-data-source>
    <class>Department</class>       
    <properties>
        <property name="hibernate.dialect" value="org.hibernate.dialect.Oracle10gDialect" />
        <property name="show_sql" value="false"/>
    </properties>
</persistence-unit>

在standalone-full.xml中

   <datasources>
       ...
       <datasource jta="true" jndi-name="java:jboss/datasources/OracleDS" pool-name="OjdbcPool" enabled="true" use-java-context="true">
                <connection-url>jdbc:oracle:thin:@localhost:1521:xe</connection-url>
                <driver>ojdbc</driver>
                <pool>
                    <min-pool-size>10</min-pool-size>
                    <max-pool-size>20</max-pool-size>
                    <prefill>true</prefill>
                </pool>
                <security>
                    <user-name>xxx</user-name>
                    <password>xxx</password>
                </security>
            </datasource>
            <drivers>
                <driver name="ojdbc" module="oracle.jdbc">
                    <xa-datasource-class>oracle.jdbc.OracleDriver</xa-datasource-class>
                </driver>
            </drivers>

   </datasources>

【问题讨论】:

    标签: hibernate jakarta-ee jpa transactions ejb-3.1


    【解决方案1】:

    persist() 有一个锁在表/行上(嗯,这是可配置的),由于某种原因,Tx 无法回滚……直到超时到来。

    Department实体看起来如何?与表正确匹配?ORM生成的sqlinsert如何?

    至少 EJB 代码看起来没问题,如果您确定实体正确映射表,您可以专注于数据库/ORM 及其锁。

    选项:有时我会建议抛出 runtimeException(IllegalStateExceptionIllegalArgumentException 或自定义)而不是 setRollback,容器将自动标记回滚 Tx(并退出为尽快从方法中),这将使您的代码更具表现力。

    【讨论】:

    • 谢谢,我会尽快发布我的实体类。即使我注释掉我所有的事务管理代码,我的应用程序仍然挂在persist()!
    • 我认为这与连接池有关或连接处于打开状态且未提交?
    • 嗯,这是一个可以验证的选项(虽然很奇怪,JPA 不会尝试为每个操作打开和关闭连接,它们是按需汇集和共享的),如果您可以监控将很有帮助交易并寻找锁,我会尝试在我的系统上复制你的问题......没有承诺。
    • 谢谢 Chechus,我怎样才能最好地监控事务和锁?抱歉,以前从未这样做过!
    • 我同时运行了 SQLDeveloper,这导致我的表被锁定,因为我删除了一条记录并试图在下一刻从 UI 添加而没有意识到提交(在自动的印象下-犯罪)。我已经运行了一个脚本来找出表锁,因为我释放了然后来自 UI 的事务继续进行。感谢您的帮助,您应该得到 +100!
    【解决方案2】:

    问题在于这是一个 XA 数据源定义,非 XA 驱动程序正在传递给该定义。

    XA 数据源允许参与多资源事务,例如,可以执行跨两个数据库上的表的事务。

    请参阅此处以获取 setting up and XA datasource 的 Oracle 示例,您将需要 oracle.jdbc.xa.client.OracleXADataSource

    XA 事务与two-phase commit protocol 一起工作,所有参与者投票以查看事务是否“可提交”,并且只有在第二步才实际执行提交(或回滚)。

    这里似乎 JTA 事务管理器挂起等待提交确认,但从未收到它,因为使用的数据源不是 XA 数据源,所以它不知道两阶段提交协议。

    作为一种解决方案,如果您不需要 XA,因为多资源事务不是必需的,那么只需将数据源设为非 XA - 例如local-tx-datasource

    否则 id 数据源需要是 XA 然后点击上面的链接以获取有关配置 XA 数据源的更多详细信息。

    【讨论】:

    • 令人惊讶的是,我的代码有效!似乎在 XA 数据源 xml 元素中使用非 XA 数据源并不重要,在我的情况下,这可能只是非 XA。但是,您说得对,因为等待我的 SQLDeveloper 提交/回滚,我无法从 UI 中获取表。
    猜你喜欢
    • 2016-03-02
    • 2015-04-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-19
    • 2018-09-13
    • 1970-01-01
    相关资源
    最近更新 更多