2015-06-23 2 views
1

Может ли кто-нибудь помочь мне понять, как установить уровень изоляции SNAPSHOT в конфигурации Spring's XML?Как установить уровень изоляции SNAPSHOT весной

Я занимаюсь проектом, который раньше разрабатывался кем-то другим, и в некоторых случаях мы получаем взаимоблокировки при работе с базой данных. Я проверил, что, несмотря на уровень изоляции БД SNAPSHOT, когда приложение выдает запрос, уровень изоляции для этой транзакции изменяется на READ_COMMITTED. Согласно моему краткому исследованию, если не задано явно, hibernate использует изоляцию DEFAULT, которая для SQLServer 2012 равна READ_COMMITTED.

К сожалению, я не являюсь экспертом в любом весной или Hibernate, так что я просто дам конфиги, которые кажутся уместным:

<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean"> 
    <property name="jndiName"> 
     <value>jdbc/ds</value> 
    </property> 
</bean> 

<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> 
    <property name="dataSource" ref="dataSource" />  
    <property name="mappingResources"> 
     <list> 
      ... 
     </list> 
    </property> 

    <property name="hibernateProperties"> 
     <props> 
      <prop key="hibernate.dialect">${nn.hibernate.dialect}</prop> 
      <prop key="hibernate.show_sql">${nn.hibernate.showSQL}</prop> 
      <prop key="hibernate.generate_statistics">${nn.hibernate.generatestatics}</prop> 
      <prop key="hibernate.hbm2ddl.auto">${nn.hibernate.hbm2ddl}</prop> 
      <prop key="hibernate.jdbc.batch_size">${nn.hibernate.batchsize}</prop> 
      <prop key="hibernate.cache.provider_class">${nn.hibernate.cache.provider_class}</prop> 
      <prop key="hibernate.cache.use_second_level_cache">${nn.hibernate.cache.use_second_level_cache}</prop> 
     </props> 
    </property> 
</bean> 


<bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> 
    <property name="sessionFactory"> 
     <ref local="sessionFactory" /> 
    </property> 
</bean> 


<tx:advice id="txAdvice" transaction-manager="txManager"> 
    <tx:attributes> 
     <tx:method name="save*" read-only="false" rollback-for="NNDBException"/> 
     <tx:method name="update*" read-only="false" rollback-for="NNDBException"/> 
     <tx:method name="checkFor*" read-only="false" rollback-for="NNDBException"/> 
     <tx:method name="*"/> 
    </tx:attributes> 
</tx:advice> 


<bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate"> 
    <property name="sessionFactory" ref="sessionFactory" /> 
</bean> 

При исследовании возможных решений я также узнал, что установка hibernate.connection.isolation когда DataSource предоставляется не является эффективным.

Оттуда я добрался до this example, где IsolationLevelDataSourceAdapter используется для установки уровня изоляции для каждого экземпляра Connection. Конфиги стал этим:

<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean"> 
    <property name="jndiName"> 
     <value>jdbc/ds</value> 
    </property> 
</bean> 


<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> 
    <property name="dataSource"> 
     <bean class="org.springframework.jdbc.datasource.IsolationLevelDataSourceAdapter"> 
      <property name="targetDataSource" ref="dataSource"/> 
      <property name="isolationLevel" value="4096" /> 
     </bean> 
    </property> 
    <property name="mappingResources"> 
     <list> 
      ... 
     </list> 
    </property> 
    <property name="hibernateProperties"> 
     <props> 
      <prop key="hibernate.dialect">${nn.hibernate.dialect}</prop> 
      <prop key="hibernate.show_sql">${nn.hibernate.showSQL}</prop> 
      <prop key="hibernate.generate_statistics">${nn.hibernate.generatestatics}</prop> 
      <prop key="hibernate.hbm2ddl.auto">${nn.hibernate.hbm2ddl}</prop> 
      <prop key="hibernate.jdbc.batch_size">${nn.hibernate.batchsize}</prop> 
      <prop key="hibernate.cache.provider_class">${nn.hibernate.cache.provider_class}</prop> 
      <prop key="hibernate.cache.use_second_level_cache">${nn.hibernate.cache.use_second_level_cache}</prop> 
     </props> 
    </property> 
</bean> 


<bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> 
    <property name="sessionFactory"> 
     <ref local="sessionFactory" /> 
    </property> 
    <property name="allowCustomIsolationLevels" value="true" /> 
</bean> 


<tx:advice id="txAdvice" transaction-manager="txManager"> 
    <tx:attributes> 
     <tx:method name="save*" read-only="false" rollback-for="NNDBException"/> 
     <tx:method name="update*" read-only="false" rollback-for="NNDBException"/> 
     <tx:method name="checkFor*" read-only="false" rollback-for="NNDBException"/> 
     <tx:method name="*"/> 
    </tx:attributes> 
</tx:advice> 


<bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate"> 
    <property name="sessionFactory" ref="sessionFactory" /> 
</bean> 

где установлен уровень изоляции 4096 в sessionFactory. Тем не менее, это то место, где я попал в стену: IllegalArgumentException: Only isolation constants allowed, который, как я полагаю, равен DEFAULT, READ_UNCOMMITTED, READ_COMMITTED, REPEATABLE_READ и SERIALIZABLE.

Есть ли проверенный способ установить уровень изоляции на SNAPSHOT (или 4096) в контексте конфигураций, которые у меня есть?

спасибо.

+0

Поскольку вы получить источник данных из JNDI, вы должны найти способ настройки уровня изоляции в реестре JNDI. Это может быть или не быть возможным в зависимости от используемой вами реализации JNDI. Даже если у вас есть локальный (определенный в XML) источник данных, разные источники данных имеют разные механизмы настройки уровня изоляции. Например, Atomikos позволяет установить целочисленное значение для уровня изоляции, тогда как HikariCP принимает только строку. Таким образом, вы могли бы использовать '4096' в качестве возможного уровня изоляции с Atomikos, но не с HikariCP. – manish

ответ

2

IsolationLevelDataSourceAdapter проверяет стандартные коды уровня изоляции, что является явным ограничением (я предлагаю вам записать проблему Spring JIRA для этого).

Чтобы обойти это, вам нужно расширить IsolationLevelDataSourceAdapter класс:

public class CustomIsolationLevelDataSourceAdapter extends IsolationLevelDataSourceAdapter { 

    private final Integer customIsolationLevel; 

    public CustomIsolationLevelDataSourceAdapter(Integer customIsolationLevel) { 
     this.customIsolationLevel = customIsolationLevel; 
    } 

    @Override 
    protected Integer getIsolationLevel() { 
     return customIsolationLevel != null ? customIsolationLevel : super.getIsolationLevel(); 
    } 
} 

и использовать dataSource вместо:

<bean class="my.package.CustomIsolationLevelDataSourceAdapter"> 
    <constructor-arg value="4096"/> 
</bean> 
Смежные вопросы