编辑:当我打开Glassfish的事务记录时:
CLASSNAME: com.sun.enterprise.transaction.JavaEETransactionImpl --Created new JavaEETransactionImpl, txId = 21
Hibernate: update ...
Hibernate: delete ...
CLASSNAME: com.sun.enterprise.transaction.JavaEETransactionImpl --In JavaEETransactionImpl.commit, jtsTx=null nonXAResource=null
运行两个sql语句后, JavaEETransactionImpl
正确提交。
我还在交易期间(更新后和删除前)检查了C3P0连接的实例,Connection.getAutoCommit()
返回true
!这是什么原因,为什么调用getEntityManager().flush()
时会提交sql语句。
AFAIK Connection在交易过程中不应处于autoCommit模式,Hibernate有责任将其关闭。当我关闭autoCommit时,在MultiTenantConnectionProvider
中创建Connection实例时,永远不会提交更改。
所以问题是, Hibernate没有关闭连接的autoCommit,也没有在事务发生后调用connection.commit()
。(提交仅执行,因为默认的autoCommit设置为在C3P0中为真)。的为什么吗
进行以下设置:
Glassfish 4.0,Hibernate 5.0.7使用数据库方法为multi-tenancy设置,通过MultiTenantConnectionProvider
实现和MS SQL Server 2014为Hibernate提供C3P0连接,
事务无效。
例如,我在无状态会话bean中有一个删除实体的业务方法:
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public void remove(IPersistentObject entity, IUser user) {
entity.setModifiedBy(user.getIdentification());
entity.setModifiedDate(ZonedDateTime.now());
entity.setStatus(DataRecordStatus.DELETED);
IPersistentObject merge = getEntityManager().merge(entity);
getEntityManager().flush();
getEntityManager().remove(merge);
getEntityManager().flush();
}
在第一步中,此方法设置有关执行删除的人员和时间的实体元数据。之后,调用flush()以触发数据库更新触发器,从而将更改保存到历史记录表中。之后,实体将从实时(非历史)表中删除。
问题,这不是在一个事务中执行的。当我调试代码时,在第一次刷新之后,我可以看到数据库中的DELETED状态,尽管事务应该仍在运行并且只在EJB方法结束后提交。
当我为一个实体执行此方法时,由于它在另一个表中被引用而无法删除,因此会抛出ConstraintViolationException
,但元数据更改不会回滚,并且实体仍处于损坏状态(DELETED)状态)。
的persistence.xml:
<persistence version="2.0" 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">
<persistence-unit name="sqlServerTestPU" transaction-type="JTA">
<!-- 1 -->
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<!-- 2 -->
<!-- We are multi tenant, do not specify JTA data source
<jta-data-source>${db.jdbcName}</jta-data-source> -->
<!-- 3 -->
<properties>
<property name="hibernate.archive.autodetection" value="class"/>
<property name="hibernate.dialect" value="org.hibernate.dialect.SQLServer2008Dialect"/>
<property name="hibernate.show_sql" value="${hibernate.showSql}"/>
<property name="hibernate.format_sql" value="${hibernate.showSql}"/>
<property name="hibernate.transaction.manager_lookup_class" value="org.hibernate.transaction.SunONETransactionManagerLookup"/>
<property name="hibernate.transaction.jta.platform" value="org.hibernate.service.jta.platform.internal.SunOneJtaPlatform"/>
<property name="hibernate.enable_lazy_load_no_trans" value="true"/>
<property name="hibernate.multiTenancy" value="DATABASE"/>
<property name="hibernate.multi_tenant_connection_provider" value="at.ts.wh.dal.WHMultiTenantConnectionProvider"/>
<property name="hibernate.tenant_identifier_resolver" value="at.ts.wh.dal.WHCurrentTenantIdentifierResolver"/>
</properties>
</persistence-unit>
</persistence>
当我从MultiTenantConnectionProvider
记录检索/释放连接时,我得到类似这样的内容:
TENANT1 getConnection com.mchange.v2.c3p0.impl.NewProxyConnection@73b9aad9]]
Hibernate: update ...
Hibernate: delete ...
TENANT1 releaseConnection com.mchange.v2.c3p0.impl.NewProxyConnection@73b9aad9]]
看起来连接是为整个业务方法(事务)保留的,这是正常的,但提交是通过刷新进行的。
如何使交易有效?谢谢你的帮助!