EntityManager.persist()方法挂起

时间:2014-02-18 22:55:14

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

不确定是否有人遇到此问题。我正在使用带有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](交易收割者)ARJUNA012117:TransactionReaper :: TX 0检查超时:ffffc0a80005:57a36cd7:5303d0bf:30状态为RUN   21:56:22,767 WARN [com.arjuna.ats.arjuna](交易收割者工人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状态CANCEL   21:56:23,767 WARN [com.arjuna.ats.arjuna](交易收割者)ARJUNA012117:TransactionReaper :: TX 0检查超时:ffffc0a80005:57a36cd7:5303d0bf:30状态CANCEL_INTERRUPTED   21:56:23,768 WARN [com.arjuna.ats.arjuna](交易收割者)ARJUNA012120:TransactionReaper :: check worker线程[Transaction Reaper Worker 2,5,main]在取消TX 0时没有响应中断:ffffc0a80005:57a36cd7: 5303d0bf:30 - 标记为僵尸的工作人员和预定用于标记为回滚的TX   21:56:23,770 WARN [com.arjuna.ats.arjuna](交易收割者)ARJUNA012110:TransactionReaper ::检查成功标记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>

2 个答案:

答案 0 :(得分:2)

persist()处对表/行进行锁定(好,这是可配置的),由于某种原因,Tx无法回滚,因为......直到超时到达。

如何查看Department实体?,与表正确匹配?以及ORM生成的sql insert如何?

至少EJB代码看起来不错,如果您确定该实体正确映射了该表,您可以使用其锁定关注数据库/ ORM。

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

答案 1 :(得分:1)

问题在于这是一个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数据源的更多详细信息。