记录JDBC / Hibernate / JPA事务隔离级别

时间:2010-07-21 19:37:06

标签: hibernate jpa jdbc transactions isolation-level

我正在开发一个连接到Microsoft SQL Server数据库的Flex / BlazeDS / Spring / JPA / Hibernate Web应用程序。它似乎是过于激进地锁定表格。从我的研究来看,看起来使用快照隔离策略是最好的选择。

我已经这样设置了:

  <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 个答案:

答案 0 :(得分:6)

您应该将hibernate的事务隔离级别设置为2(READ_COMMITTED的java.sql.Connection常量。

然后在SQL Server 2005实例中执行以下操作(没有活动连接):

ALTER DATABASE [database_name] SET ALLOW_SNAPSHOT_ISOLATION ON; ALTER DATABASE [database_name] SET READ_COMMITTED_SNAPSHOT ON;

执行此查询进行测试:

SELECT [name],snapshot_isolation_state_desc,snapshot_isolation_state,is_read_committed_snapshot_on FROM sys.databases WHERE [name] ='database_name';

现在,在SQL Server中,READ_COMMITTED将被解释为READ_COMMITTED_SNAPSHOT。

答案 1 :(得分:2)

我想描述一下我在JPA / MySQL上遇到的问题;它可能会激发你的调查......

  • 全球交易开始
  • 事务1)表Address上的新行 (自动增量)
  • 交易2)一个新的 表上的一行Entreprise与 Addres上的外键;新的 插入的Entreprise链接到 新的地址#ID。
  • 全球交易结束

对于这种情况,使用ResourceLocal / JPATransactionManager进行MYSQL死锁。

实际上,似乎我们无法打开几个嵌套的事务。全局事务似乎与事务1)和2)合并。事务2)以死锁结束,因为无法使用表A新的未准备好的#Id来提供数据。

但是,我们可以在调试器中看到事务1和2之间的新adresse行#id。

它与您的问题相似吗?你猜一些自动增量 - 与你的僵局的关系? 以下是可能的解决方案......

  • 解决方法1 改变隔离级别? - &GT;怎么样?!!我没有答案......而且我不会这会改变任何事情。

  • 溶液2 将JPA实体ID生成策略(自动或身份)替换为自定义序列表。

  • 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;  

然后将两行保存到单个merge()中:

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

返回实例,同时返回插入的新#ids和魔法:不再死锁...

解决方案#3更智能,但需要更深入的分析并更改一些代码......

答案 2 :(得分:2)

Whenever you supply a DataSource,Hibernate将忽略hibernate.connection.isolation设置。

您需要在DataSource级别设置隔离级别。大多数连接池或XA Java EE Application Server DataSource允许您设置全局事务隔离级别,因此来自该DataSource的所有连接都继承相同的隔离级别。