2010-07-21 1 views
4

Я работаю над веб-приложением Flex/BlazeDS/Spring/JPA/Hibernate, подключенным к базе данных Microsoft SQL Server. Похоже, что блокировка таблиц слишком агрессивно. Из моих исследований, похоже, использование политики изоляции моментальных снимков - лучший выбор.Регистрация уровней изоляции транзакций JDBC/Hibernate/JPA

Я установил вещи, как, например:

<bean id="entityManagerFactory" 
     class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" lazy-init="true"> 
    <property name="persistenceUnitName" value="OrderManagerPersistenceUnit" /> 
    <property name="dataSource" ref="dataSource"/> 
    <property name="jpaVendorAdapter"> 
     <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" /> 
    </property> 
    <property name="jpaProperties"> 
     <props> 
     <prop key="hibernate.jdbc.batch_size">${db.main.hibernate.jdbc.batch_size}</prop> 
     <prop key="hibernate.hbm2ddl.auto">${db.main.hbm2ddl.auto}</prop> 
     <prop key="hibernate.search.default.indexBase">${db.main.search.default.indexBase}</prop> 
     <prop key="hibernate.search.autoregister_listeners">${db.main.search.autoregister_listeners}</prop> 
      <prop key="hibernate.show_sql">${db.main.show_sql}</prop> 
      <prop key="hibernate.dialect">${db.main.dialect}</prop> 
      <prop key="hibernate.connection.isolation">${db.main.isolation}</prop> 
      <prop key="hibernate.ejb.naming_strategy">com.herffjones.zebra.db.ZebraNamingStrategy</prop> 
     </props> 
    </property> 
    </bean> 

Однако я не уверен, что это на самом деле с помощью hibernate.connection.isolation. Похоже, я должен установить некоторые свойства в источнике данных JDBC.

Я хотел бы проверить, использует ли он в настоящее время 4096 в качестве уровня изоляции транзакций для запросов.

Какие уровни пакетов и журналов можно добавить в файл logback.xml, чтобы четко видеть уровень изоляции, который использует конкретный запрос?

Спасибо!

ответ

6

Вы должны установить уровень изоляции транзакции в спящем режиме как 2 (константа java.sql.Connection для READ_CO MMITTED.

Затем выполните следующее в вашем SQL Server 2005 экземпляр (без активных соединений):

ALTER DATABASE [database_name] SET ALLOW_SNAPSHOT_ISOLATION ON; ALTER DATABASE [имя_базы_] SET READ_COMMITTED_SNAPSHOT ON;

испытаний путем выполнения этого запроса:

SELECT [имя], snapshot_isolation_state_desc, snapshot_isolation_state, is_read_committed_snapshot_on ОТ sys.databases ГДЕ [имя] = 'имя_базы_данных';

Теперь READ_COMMITTED будет интерпретироваться как READ_COMMITTED_SNAPSHOT в SQL Server.

2

Я хотел бы описать проблему, которую я получил по JPA/MySQL; это может вдохновить своих исследований ...

  • Глобальная сделка начать
  • сделка 1) новая строка в таблице Адрес (автоинкремент)
  • сделки 2) новый ряд на столе Entreprise с иностранных ключ на столе Addres; новый Введенный Entreprise связан с новым адресом №ID.
  • Конец глобальной сделки

MYSQL мертвые замки для этого случая с ResourceLocal/JPATransactionManager.

На самом деле, кажется, что мы не можем открыть несколько вложенных транзакций. Глобальная транзакция, похоже, объединена с транзакциями 1) и 2). Transaction 2) заканчивается в тупике, потому что данные не могут быть загружены таблицей. Новый #Id, который не готов.

Однако мы можем увидеть с помощью отладчика новый адресует строка # идентификатор между транзакцией 1 и 2.

Это похоже на ваш вопрос? Вы предполагаете, что автоинкремент - отношение к вашему тупику? Эти Ниже приведены возможные решения ... Уровень изоляции

  • Solution1 Изменить? -> Как? !! У меня нет ответа ... И я не уверен, что это что-то изменит.

  • Решение2 Замените стратегию формирования идентификаторов объектов JPA (авто или личность) в таблицу пользовательских последовательностей.

  • Solution3

Проверьте, если вы не можете использовать стратегию каскадного на ManyToOne отношений.

EntrepriseEntity{ 
@Id @GeneratedValue(strategy=GenerationType.IDENTITY) 
@Column(name = "id_entreprise") 
private int id; 

@ManyToOne(fetch=FetchType.LAZY,cascade=CascadeType.ALL) 
@JoinColumn(name = "id_address") 
private AddressEntity address; 

А затем сохранить обе строки в одну слияния():

EntrepriseEntity e=new EntrepriseEntity(); 
e.setAddress(new AddressEntity()); 
e=entityManager.merge(e); 

Возвращается экземпляр с дать вам обратно как новые #ids вставленные и магия: больше не тупик ...

Решение № 3 умнее, но требует более глубокого анализа и изменения некоторого кода ...

2

Whenever you supply a DataSource, Hibernate будет игнорировать настройку hibernate.connection.isolation.

Вместо этого вам необходимо установить уровень изоляции на уровне DataSource. Большинство пулов соединений или XA Java EE Application Server DataSources позволяют установить уровень изоляции глобальной транзакции, поэтому все соединения, исходящие из этого DataSource, наследуют один и тот же уровень изоляции.