Регистрация уровней изоляции транзакций JDBC / Hibernate / JPA - PullRequest
4 голосов
/ 21 июля 2010

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

Я настроил все так:

  <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, чтобы четко видеть уровень изоляции, который использует конкретный запрос?

Спасибо!

Ответы [ 3 ]

6 голосов
/ 22 сентября 2010

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

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

ALTER DATABASE [имя_базы_данных] 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 FROM sys.databases ГДЕ [имя] = 'имя_базы данных';

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

2 голосов
/ 24 декабря 2014

Всякий раз, когда вы предоставляете источник данных , Hibernate будет игнорировать параметр hibernate.connection.isolation.

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

2 голосов
/ 29 июля 2010

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

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

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

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

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

Это похоже на вашу проблему?Угадаете ли вы автоинкремент - связь с вашим тупиком?Следующие варианты являются возможными решениями ...

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

  • Решение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 умнее, но требует более глубокого анализа и изменения кода ...

...