【问题标题】:EJB transaction not rolling backEJB 事务不回滚
【发布时间】:2014-11-10 12:08:34
【问题描述】:

我有上面的 EJB:

    @Stateless
public class ItilEJB  {
    @PersistenceContext
    protected EntityManager em;

    public <T> T find(Class<T> clazz, Long id) {
        if (clazz == null || id == null) {
            return null;
        }

        return em.find(clazz, id);
    }


public Chamado atender(Long chamadoId) {

        Chamado chamado = find(Chamado.class, chamadoId);

        if (!isChamadoAtendido(chamadoId)) {
            Status emAndamento = new Status(Status.EM_ANDAMENTO);

            HistoricoChamado historico = new HistoricoChamado();
            historico.setDescricao("Início do atendimento do chamado.");
            historico.setChamado(chamado);
            historico.setStatus(emAndamento);
            historico.setSla(chamado.getSla());

            chamado.setStatus(emAndamento);

            save(historico);

            save(chamado);
        }

        return chamado;
    }

public void save(BaseEntity entity) {

        if (entity.getId() == null) {
            if (!helper.canInsert(this, entity)) {
                throw new AlertMessageRuntimeException("user.db.constraint");
            }
            em.persist(entity);
        } else {
            if (!helper.canUpdate(this, entity)) {
                throw new AlertMessageRuntimeException("user.db.constraint");
            }
            em.merge(entity);
        }
    }

}

如果我的第二次保存,保存(chamado);抛出一个异常(无论是否运行时)第一次保存没有回滚,我不明白为什么。 对我来说,每个 EJB 调用都将封装在一个事务中,如果发生异常,与 DB 层的整个交互都将回滚。

我怎样才能完成这种行为?如果我的第二次保存引发错误,我希望回滚第一次保存操作。

谢谢


我使用 MySQL 作为 DBMS,Wildfly 8.1 作为应用服务器。 我没有更改任何默认值,所以我认为没有启用自动提交模式。

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1"
    xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
    <persistence-unit name="primary">
        <provider>org.hibernate.ejb.HibernatePersistence</provider>
        <jta-data-source>java:jboss/datasources/MySQLDS</jta-data-source>

        <properties>
            <property name="hibernate.show_sql" value="true" />
        </properties>
    </persistence-unit>
</persistence>

这是我在standalone.xml中的数据源配置

<datasource jndi-name="java:jboss/datasources/MySQLDS" enabled="${mysql.enabled}" use-java-context="true" pool-name="MySQLDS" use-ccm="true">
                    <connection-url>jdbc:mysql://${env.OPENSHIFT_MYSQL_DB_HOST}:${env.OPENSHIFT_MYSQL_DB_PORT}/${env.OPENSHIFT_APP_NAME}</connection-url>
                    <driver>mysql</driver>
                    <security>
                      <user-name>${env.OPENSHIFT_MYSQL_DB_USERNAME}</user-name>
                      <password>${env.OPENSHIFT_MYSQL_DB_PASSWORD}</password>
                    </security>
                    <validation>
                        <check-valid-connection-sql>SELECT 1</check-valid-connection-sql>
                        <background-validation>true</background-validation>
                        <background-validation-millis>60000</background-validation-millis>
                        <!--<validate-on-match>true</validate-on-match>-->
                    </validation>
                    <pool>
                        <flush-strategy>IdleConnections</flush-strategy>
                    </pool>
                </datasource>

【问题讨论】:

  • 应该回滚。您使用的是哪个 DBMS?持久化单元是如何配置的?它失败的唯一原因是激活了某种自动提交模式。
  • 碰巧你有任何部署描述符吗?是否可以在描述符中为保存方法覆盖 TransactionAttribute?

标签: java transactions ejb


【解决方案1】:

如果您偶然使用了 JBoss,则很有可能数据源被错误地定义为不使用 JTA 事务。检查您是否在 JBoss 配置中设置了 &lt;datasource jta="true" ..。更多详情请查看Transactions don't rollback

【讨论】:

  • 嗨,加油,谢谢!这是真的,我在standalone.xml 中添加了我的数据源的定义,它没有 jta="true" 属性。我现在将尝试添加。
【解决方案2】:

你没有提到 save() 方法是如何定义的。如果它使用 BMP,则它无法加入来自 CMP 的事务,例如 atender()。

如果没有,那么试试这个:

在 atender(Long chamadoId) 上放注解 @TransactionAttribute(TransactionAttributeType.REQUIRED)。并且在 save() 方法的定义上面放这个注解@TransactionAttribute(TransactionAttributeType.MANDATORY)

希望有所帮助

【讨论】:

  • 感谢您的回复!我想我已经,看问题了。
  • 抱歉,我没有注意到滑动条。但是,您可以尝试我的第二个建议。我已经读过 REQUIRED 属性类型并不总是转换为加入事务(如果它存在),有时它会创建一个新事务,就像定义了 REQUIRES_NEW 属性一样。老实说,我不记得我在哪里找到了这个,但我遇到了和你类似的问题;但是,尝试使用我之前回复的第二部分,它应该强制 save() 方法不启动新事务并加入调用者的事务。另外,试试
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-12-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-21
  • 1970-01-01
相关资源
最近更新 更多