EJB 回滚在提交异常时不适用于容器管理事务或 Bean 管理事务
EJB Rollback does not work with Container Management Transaction or Bean Managament Transaction on commit exception
我花了几个小时尝试使用 EJB 进行回滚。我有一个 CDI 控制器,我想在其中删除一些对象。当我尝试在 EJB 中删除时出现异常,我尝试进行回滚,但它不起作用。每一个SQL在get异常前执行过commit的都不会回滚。显然这不是因为当我尝试在 BMT 中进行回滚时遇到另一个异常。否则,当我尝试使用 CMT 时,我得到一个休眠异常,但我得到的结果与 BMT 相同。
我的控制器是
@Named
@Stateful
@ConversationScoped
public class PRequerimientoConjuntoCertificacionesBean implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1779474550283190942L;
@Inject
private Conversation conversation;
@PersistenceContext(type = PersistenceContextType.TRANSACTION)
private EntityManager entityManager;
@Inject
private DatosSesion datosSesion;
public void eliminarDocumento() {
// TODO hay que probarlo
DocumentoGeneradoSSCC documentoEliminar;
try {
documentoEliminar = (DocumentoGeneradoSSCC) daoBase
.getEntityById(DocumentoGeneradoSSCC.class,
10);
documentoSSCCDAOBean.removeDocumentoSSCC(documentoEliminar,entityManager);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
使用 EJB BMT 如下:
@Stateful
@TransactionManagement(TransactionManagementType.BEAN)
public class DocumentoSSCCDAOBean implements IDocumentoSSCCDAOBeanLocal {
@Resource
private UserTransaction userTran;
@PersistenceContext(type = PersistenceContextType.TRANSACTION)
private EntityManager entityManager;
@Override
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public void removeDocumentoSSCC(
DocumentoGeneradoSSCC documentoGeneradoSSCC,
EntityManager entityManager) {
// TODO hue probarlo
try {
userTran.begin();
// Eliminamos recurso asignado
entityManager
.remove(entityManager.contains(documentoGeneradoSSCC) ? documentoGeneradoSSCC
: entityManager.merge(documentoGeneradoSSCC));
userTran.commit();
} catch (Exception e) {
try {
userTran.rollback();
} catch (IllegalStateException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (SecurityException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (SystemException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
}
我得到了这个堆栈跟踪
javax.transaction.RollbackException: ARJUNA016053: Could not commit transaction.
当我尝试回滚时,我得到了这个
java.lang.IllegalStateException: BaseTransaction.rollback - ARJUNA016074: no transaction!
我有 JTA=true 的独立数据源,
<datasource jta="true" jndi-name="java:jboss/datasources/ExampleDS" pool-name="ExampleDS" enabled="true" use-java-context="true">
<connection-url>jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE</connection-url>
<driver>h2</driver>
<security>
<user-name>sa</user-name>
<password>sa</password>
</security>
</datasource>
我的persistence.xml是
<persistence-unit name="JusticiaGratuita"
transaction-type="JTA">
<!-- <description>Forge Persistence Unit</description> -->
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<jta-data-source>java:jboss/datasources/ExampleDS</jta-data-source>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<properties>
<property name="hibernate.connection.driver_class" value="${db.driver}" />
<property name="hibernate.connection.url" value="${db.url}" />
<property name="hibernate.connection.username" value="${db.user}" />
<property name="hibernate.connection.password" value="${db.pass}" />
<property name="hibernate.default_schema" value="${db.schema}" />
<property name="hibernate.dialect" value="org.hibernate.dialect.Oracle10gDialect" />
<property name="hibernate.hbm2ddl.auto" value="validate" />
<property name="hibernate.query.substitutions" value="true 1, false 0,'SI' 1, 'NO' 0" />
<property name="hibernate.cache.provider_class" value="org.hibernate.cache.EhCacheProvider" />
<property name="hibernate.jdbc.batch_size" value="20" />
<property name="hibernate.cache.use_second_level_cache"
value="true" />
<property name="hibernate.cache.use_query_cache" value="false" />
<property name="hibernate.show_sql" value="${db.showSql}" />
<property name="hibernate.format_sql" value="true" />
<property name="hibernate.connection.provider_class"
value="org.hibernate.service.jdbc.connections.internal.C3P0ConnectionProvider" />
<property name="hibernate.c3p0.max_size" value="30" />
<property name="hibernate.c3p0.min_size" value="5" />
<property name="hibernate.c3p0.acquire_increment" value="1" />
<property name="hibernate.c3p0.idle_test_period" value="3000" />
<property name="hibernate.c3p0.max_statements" value="0" />
<property name="hibernate.c3p0.timeout" value="0" />
<property name="hibernate.c3p0.autocommit" value="false" />
</properties>
</persistence-unit>
您可以在此处查看我的错误的完整堆栈跟踪:http://pastebin.com/h17JD2xP
如果能帮助我回滚和解决我的问题,我将不胜感激。
此致
终于解决了我的问题。我得到这个异常是因为在执行回滚之前我执行了提交,因此在提交之后不可能执行回滚,因为它们彼此排斥。原因是我没有交易,因为提交关闭它并且当回滚执行时没有交易。
java.lang.IllegalStateException: BaseTransaction.rollback -
ARJUNA016074: no transaction!
最后我决定这样用CMT做。
@TransactionManagement(TransactionManagementType.CONTAINER)
@Stateless
public class DocumentoSSCCServiceBean implements IDocumentoSSCCServiceBeanLocal {
@EJB
private IDaoBase daoBase;
@PersistenceContext(unitName = "JusticiaGratuita", type = PersistenceContextType.TRANSACTION)
private EntityManager entityManager;
@Resource
private EJBContext ejbContext;
@Override
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public void removeDocumentoSSCC(Long documentoGeneradoSSCC)
throws RollbackSajgException {
try {
// Buscamos el documento a eliminar
DocumentoGeneradoSSCC docu = (DocumentoGeneradoSSCC) daoBase
.getEntityById(DocumentoGeneradoSSCC.class,
documentoGeneradoSSCC);
entityManager.remove(docu);
} catch (Exception e) {
ejbContext.setRollbackOnly();
throw new RollbackSajgException();
}
}
}
希望对大家有所帮助。
我花了几个小时尝试使用 EJB 进行回滚。我有一个 CDI 控制器,我想在其中删除一些对象。当我尝试在 EJB 中删除时出现异常,我尝试进行回滚,但它不起作用。每一个SQL在get异常前执行过commit的都不会回滚。显然这不是因为当我尝试在 BMT 中进行回滚时遇到另一个异常。否则,当我尝试使用 CMT 时,我得到一个休眠异常,但我得到的结果与 BMT 相同。
我的控制器是
@Named
@Stateful
@ConversationScoped
public class PRequerimientoConjuntoCertificacionesBean implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1779474550283190942L;
@Inject
private Conversation conversation;
@PersistenceContext(type = PersistenceContextType.TRANSACTION)
private EntityManager entityManager;
@Inject
private DatosSesion datosSesion;
public void eliminarDocumento() {
// TODO hay que probarlo
DocumentoGeneradoSSCC documentoEliminar;
try {
documentoEliminar = (DocumentoGeneradoSSCC) daoBase
.getEntityById(DocumentoGeneradoSSCC.class,
10);
documentoSSCCDAOBean.removeDocumentoSSCC(documentoEliminar,entityManager);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
使用 EJB BMT 如下:
@Stateful
@TransactionManagement(TransactionManagementType.BEAN)
public class DocumentoSSCCDAOBean implements IDocumentoSSCCDAOBeanLocal {
@Resource
private UserTransaction userTran;
@PersistenceContext(type = PersistenceContextType.TRANSACTION)
private EntityManager entityManager;
@Override
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public void removeDocumentoSSCC(
DocumentoGeneradoSSCC documentoGeneradoSSCC,
EntityManager entityManager) {
// TODO hue probarlo
try {
userTran.begin();
// Eliminamos recurso asignado
entityManager
.remove(entityManager.contains(documentoGeneradoSSCC) ? documentoGeneradoSSCC
: entityManager.merge(documentoGeneradoSSCC));
userTran.commit();
} catch (Exception e) {
try {
userTran.rollback();
} catch (IllegalStateException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (SecurityException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (SystemException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
}
我得到了这个堆栈跟踪
javax.transaction.RollbackException: ARJUNA016053: Could not commit transaction.
当我尝试回滚时,我得到了这个
java.lang.IllegalStateException: BaseTransaction.rollback - ARJUNA016074: no transaction!
我有 JTA=true 的独立数据源,
<datasource jta="true" jndi-name="java:jboss/datasources/ExampleDS" pool-name="ExampleDS" enabled="true" use-java-context="true">
<connection-url>jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE</connection-url>
<driver>h2</driver>
<security>
<user-name>sa</user-name>
<password>sa</password>
</security>
</datasource>
我的persistence.xml是
<persistence-unit name="JusticiaGratuita"
transaction-type="JTA">
<!-- <description>Forge Persistence Unit</description> -->
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<jta-data-source>java:jboss/datasources/ExampleDS</jta-data-source>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<properties>
<property name="hibernate.connection.driver_class" value="${db.driver}" />
<property name="hibernate.connection.url" value="${db.url}" />
<property name="hibernate.connection.username" value="${db.user}" />
<property name="hibernate.connection.password" value="${db.pass}" />
<property name="hibernate.default_schema" value="${db.schema}" />
<property name="hibernate.dialect" value="org.hibernate.dialect.Oracle10gDialect" />
<property name="hibernate.hbm2ddl.auto" value="validate" />
<property name="hibernate.query.substitutions" value="true 1, false 0,'SI' 1, 'NO' 0" />
<property name="hibernate.cache.provider_class" value="org.hibernate.cache.EhCacheProvider" />
<property name="hibernate.jdbc.batch_size" value="20" />
<property name="hibernate.cache.use_second_level_cache"
value="true" />
<property name="hibernate.cache.use_query_cache" value="false" />
<property name="hibernate.show_sql" value="${db.showSql}" />
<property name="hibernate.format_sql" value="true" />
<property name="hibernate.connection.provider_class"
value="org.hibernate.service.jdbc.connections.internal.C3P0ConnectionProvider" />
<property name="hibernate.c3p0.max_size" value="30" />
<property name="hibernate.c3p0.min_size" value="5" />
<property name="hibernate.c3p0.acquire_increment" value="1" />
<property name="hibernate.c3p0.idle_test_period" value="3000" />
<property name="hibernate.c3p0.max_statements" value="0" />
<property name="hibernate.c3p0.timeout" value="0" />
<property name="hibernate.c3p0.autocommit" value="false" />
</properties>
</persistence-unit>
您可以在此处查看我的错误的完整堆栈跟踪:http://pastebin.com/h17JD2xP
如果能帮助我回滚和解决我的问题,我将不胜感激。
此致
终于解决了我的问题。我得到这个异常是因为在执行回滚之前我执行了提交,因此在提交之后不可能执行回滚,因为它们彼此排斥。原因是我没有交易,因为提交关闭它并且当回滚执行时没有交易。
java.lang.IllegalStateException: BaseTransaction.rollback - ARJUNA016074: no transaction!
最后我决定这样用CMT做。
@TransactionManagement(TransactionManagementType.CONTAINER)
@Stateless
public class DocumentoSSCCServiceBean implements IDocumentoSSCCServiceBeanLocal {
@EJB
private IDaoBase daoBase;
@PersistenceContext(unitName = "JusticiaGratuita", type = PersistenceContextType.TRANSACTION)
private EntityManager entityManager;
@Resource
private EJBContext ejbContext;
@Override
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public void removeDocumentoSSCC(Long documentoGeneradoSSCC)
throws RollbackSajgException {
try {
// Buscamos el documento a eliminar
DocumentoGeneradoSSCC docu = (DocumentoGeneradoSSCC) daoBase
.getEntityById(DocumentoGeneradoSSCC.class,
documentoGeneradoSSCC);
entityManager.remove(docu);
} catch (Exception e) {
ejbContext.setRollbackOnly();
throw new RollbackSajgException();
}
}
}
希望对大家有所帮助。