4

我正在开发一个连接到 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 文件中以清楚地查看特定查询正在使用的隔离级别?

谢谢!

4

3 回答 3

7

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

然后在您的 SQL Server 2005 实例中执行以下命令(没有活动连接):

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

通过执行此查询进行测试:

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

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

于 2010-09-22T15:17:32.257 回答
2

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

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

在这种情况下,使用 ResourceLocal / JPATransactionManager 的 MYSQL 死锁。

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

但是,我们可以通过调试器看到事务 1 和事务 2 之间的新地址 row#id。

和你的问题类似吗?你猜一些自动增量 - 与你的死锁有关吗?以下是可能的解决方案...

  • 解决方案1 ​​更改隔离级别?-> 如何?!!我没有答案...而且我不知道这会改变什么。

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

  • 解决方案3

检查您是否不能对多对一关系使用级联策略。

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 更智能,但需要更深入的分析和更改一些代码......

于 2010-07-29T16:55:34.063 回答
2

每当您提供 DataSource时,Hibernate 都会忽略该hibernate.connection.isolation设置。

您需要改为在 DataSource 级别设置隔离级别。大多数连接池或 XA Java EE 应用程序服务器数据源允许您设置全局事务隔离级别,因此来自该数据源的所有连接都继承相同的隔离级别。

于 2014-12-24T07:16:36.080 回答