2012-07-19 164 views
0

我读过本教程:http://docs.oracle.com/javase/tutorial/jdbc/basics/transactions.html但我想我仍然错过了一些东西。JDBC Transaction如何锁定TRANSACTION_READ_COMMITTED隔离级别的表?

让我们举一个例子:

  • 线程T1都有各自的连接
  • 线程T2都有各自的连接

因此,这些线程执行事务上(的setAutoCommit(假)两个不同的连接)。本次交易执行,对单个数据库表,以下查询:

  • 选择一行读取一个渐进的数量(PN)
  • 插入一行逐步号码设置为:PN ++(我所
    阅读+1)

在此表中,进度号必须唯一(它是主键)。

执行JDBC事务(具有TRANSACTION_READ_COMMITTED隔离级别)避免了T1和T2读取相同PN值的问题,并且都尝试在表中插入相同的PN ++?表被锁定,直到Insert被执行并且commit()被调用?

回答

1

不,为了确保您始终拥有唯一的编号,您将需要: 1)[更好]根据DB 将DB字段更改为标识/序列/自动编号2)使用UUID作为标识符 3)[最差]在读/递增/写序列期间锁定行

TRANSACTION_READ_COMMITTED将只确保您只能读取已提交给数据库的数据。即如果你有你的

UPDATE sequence 

commit 

其他线程之间的另一个200个DB操作将无法读取你,直到你提交更新的数据,所以实际上它会做完全相反的你想要什么。

+0

的问题是,在我的情况下,主键也形成由其他两个字段(年和月),而不是只用逐行扫描数量,这必须是唯一的,那么,在一个月的一年,并从零开始另一个月 – 2012-07-19 11:38:33

+1

那么恐怕在读取,增量,更新期间锁定行可能是唯一的方法。 – 2012-07-19 11:41:53

0

您也可以在应用程序级别进行同步。这是可行的,只要一个应用程序中只有一个方法正在执行增量。

private **synchronized** void increment() { 
    Calendar calendar = Calendar.getInstance(); 
    int year = calendar.get(Calendar.YEAR); 
    int current = dao.getMaxNumber(year); 
    dao.insertNumber(year, current+1); 
}