Spring中实现SQL Server with(nolock) hint

在SQL Server的使用过程中,为了避免读锁,提高查询效率或不在乎脏读的场景下,通常会在SQL语句中使用 with(nolock) hint。那么在Spring下如何获得相同的效果呢?下面介绍下具体实现和验证过程。

实现

nolock是一个SQL Server独有的hint指令,肯定不能硬编码的方式实现,否则切换数据库的时候会痛不欲生。nolock是一种锁机制,很容易想到应该将其转换为事务级别来在java中实现。通过查阅MSDN得知,nolock 等同于 事务级别为:read uncommitted。

Spring 提供了@Transactional注解,在这个注解可以针对类或者方法设置事务级别。现我们通过这个注解,设置事务级别为READ_UNCOMMITTED。如下例:

1
2
3
@Transactional(isolation = Isolation.READ_UNCOMMITTED)
@Query(value = "select xjjgk from MisxjjgkEntity xjjgk where xjjgk.jlzt = 0 and xjjgk.bgdh = ?1 and xjjgk.jzlb = ?2 and xjjgk.yljgdm = ?3")
List<MisxjjgkEntity> getMisxjjgkEntitiesByBgdh(String bgdh, String jzlb, String yljgdm);

验证

我们使用以下语句锁住一行

1
2
3
BEGIN TRAN
UPDATE CDR_MIS_XJJGK SET jyysmc='lefer' WHERE bgdh='9570072';
-- ROLLBACK

在SQL Server中执行select,发现一直在转圈圈,确认该行已被锁。

1
select * from CDR_MIS_XJJGK where bgdh='9570072';

编写一个test,进行测试

1
2
3
4
@Test
public void contextLoads() {
Assert.assertEquals(misxjjgkDAO.getMisxjjgkEntitiesByBgdh("9570072","2","0006").size(),1);
}

test成功,很顺利的读出了被锁的行。此时我们去掉@Transactional注解,再次执行test。发现一直在转圈圈,处于被锁状态。

由此得知,该注解工作正常,达到了预期目标。

END