不确定是否有人遇到此问题。我正在使用带有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>
答案 0 :(得分:2)
在persist()
处对表/行进行锁定(好,这是可配置的),由于某种原因,Tx无法回滚,因为......直到超时到达。
如何查看Department
实体?,与表正确匹配?以及ORM生成的sql insert
如何?
至少EJB代码看起来不错,如果您确定该实体正确映射了该表,您可以使用其锁定关注数据库/ ORM。
选项:有时候我会建议抛出一个runtimeException(IllegalStateException
,IllegalArgumentException
或者一个自定义)而不是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数据源的更多详细信息。