我正在开发一个连接到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文件中,以清楚地看到特定查询正在使用的隔离级别?
谢谢!
答案 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上遇到的问题;它可能会激发你的调查......
对于这种情况,使用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的所有连接都继承相同的隔离级别。