JPA本身不提供事务的隔离级别这个概念,所以如果直接配置如 isolation="READ_COMMITTED" 时,后台会报异常
Standard JPA does not support custom isolation levels - use a special JpaDialect
如果想使用配置隔离级别需要自己写代码让jpa支持,代码里面用的是hibernate4。
public class HibernateJpaIsolationSupportDialect extends HibernateJpaDialect {
private static final long serialVersionUID = 1L;
private Logger logger = LoggerFactory
.getLogger(HibernateJpaIsolationSupportDialect.class);
@Override
public Object beginTransaction(final EntityManager entityManager,
final TransactionDefinition definition)
throws PersistenceException, SQLException, TransactionException {
if (definition.getTimeout() != TransactionDefinition.TIMEOUT_DEFAULT) {
getSession(entityManager).getTransaction().setTimeout(
definition.getTimeout());
}
if (logger.isDebugEnabled()) {
logger.debug(
"Transaction Info: IsolationLevel={} , PropagationBehavior={} , Timeout={} , Name={}",
new Object[] { definition.getIsolationLevel(),
definition.getPropagationBehavior(),
definition.getTimeout(), definition.getName()});
}
logger.debug("The isolation level set on the transaction is {}",
definition.getIsolationLevel());
ConnectionHandle connHandle = getJdbcConnection(entityManager, definition.isReadOnly());
Connection conn = connHandle.getConnection();
Integer previousIsolationLevel = DataSourceUtils
.prepareConnectionForTransaction(conn, definition);
logger.debug("The previousIsolationLevel {}", previousIsolationLevel);
entityManager.getTransaction().begin();
Object transactionData = prepareTransaction(entityManager,
definition.isReadOnly(), definition.getName());
return new IsolationSupportSessionTransactionData(transactionData,
previousIsolationLevel, conn);
}
@Override
public void cleanupTransaction(Object transactionData) {
IsolationSupportSessionTransactionData isstd = (IsolationSupportSessionTransactionData) transactionData;
super.cleanupTransaction(isstd.getSessionTransactionData());
isstd.resetIsolationLevel();
}
private static class IsolationSupportSessionTransactionData {
private final Object sessionTransactionData;
private final Integer previousIsolationLevel;
private final Connection connection;
public IsolationSupportSessionTransactionData(
Object sessionTransactionData,
Integer previousIsolationLevel, Connection connection) {
this.sessionTransactionData = sessionTransactionData;
this.previousIsolationLevel = previousIsolationLevel;
this.connection = connection;
}
public void resetIsolationLevel() {
if (this.previousIsolationLevel != null) {
DataSourceUtils.resetConnectionAfterTransaction(connection,
previousIsolationLevel);
}
}
public Object getSessionTransactionData() {
return this.sessionTransactionData;
}
}
}
然后事务配置里面使用我们自己写的HibernateJpaIsolationSupportDialect。
<!-- transactionManager -->
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
<property name="jpaDialect">
<bean class="framework.support.hibernate.HibernateJpaIsolationSupportDialect" />
</property>
</bean>
,另外entityManagerFactory里面的jpaVendorAdapter,不要使用否则HibernateJpaIsolationSupportDialect不起作用。
<!-- <property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="generateDdl" value="false"/>
<property name="database" value="MYSQL"/>
</bean>
</property> -->