SELECT FOR UPDATE不适用于JDBC和Oracle

SELECT FOR UPDATE not working with JDBC and Oracle

我写了一个简单的Java程序,它打开一个事务,选择一些记录,执行一些逻辑,然后更新它们。我希望记录被锁定,所以我使用SELECT ... FOR UPDATE。

该程序可与MS SQL Server 2005完美配合,但在Oracle 10g中,记录未锁定!

知道为什么吗?

我按如下方式创建连接:

1
2
Connection connection = DriverManager.getConnection(URL, User, Password);
connection.setAutoCommit(false);

如果我从Oracle SQL Developer客户端执行SELECT..FOR UPDATE,则可以看到记录已锁定,因此我认为这可能是JDBC驱动程序的问题,而不是数据库的问题,但我无法在网上找不到有用的东西。

这些是我正在使用的JDBC驱动程序的详细信息:

1
2
3
4
5
6
7
8
9
10
Manifest-Version: 1.0
Implementation-Vendor:  Oracle Corporation
Implementation-Title:   ojdbc14.jar
Implementation-Version: Oracle JDBC Driver version -"10.2.0.2.0"
Implementation-Time:    Tue Jan 24 08:55:21 2006
Specification-Vendor:   Oracle Corporation
Sealed: true
Created-By: 1.4.2_08 (Sun Microsystems Inc.)
Specification-Title:    Oracle JDBC driver classes for use with JDK14
Specification-Version:  Oracle JDBC Driver version -"10.2.0.2.0"


对不起,我无法重现此行为。究竟如何在JDBC中运行SELECT ... FOR UPDATE查询?

我有一个表locktest,其中包含以下数据:

1
2
3
4
5
6
7
8
9
SQL> select * from locktest;

         A          B
---------- ----------
         1          0
         2          0
         3          0
         4          0
         5          0

我也有这个Java类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import oracle.jdbc.OracleDriver;
import java.sql.*;

public class LockTest {

    public static void main(String[] args) throws Exception {
        DriverManager.registerDriver(new OracleDriver());
        Connection c  = DriverManager.getConnection(
           "jdbc:oracle:thin:@localhost:1521:XE","user","password");

        c.setAutoCommit(false);
        Statement stmt = c.createStatement(
            ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE);

        ResultSet rSet = stmt.executeQuery(
           "SELECT a, b FROM locktest FOR UPDATE");

        while (rSet.next()) {
            if (rSet.getInt(1) <= 3) {
                rSet.updateInt(2, 1);
            }
        }

        System.out.println("Sleeping...");
        Thread.sleep(Long.MAX_VALUE);
    }
}

当我运行此Java类时,它将对表进行一些更新,然后开始hibernate。它处于hibernate状态,以使事务保持打开状态,从而保留了锁。

1
2
C:\\Users\\Luke\\stuff>java LockTest
Sleeping...

这是在hibernate时,我尝试同时更新SQL * Plus中的表:

1
SQL> update locktest set b = 1 where a <= 3;

这时,SQL * Plus挂起,直到我杀死Java程序。