如何在 SQLITE 中启动即时事务 JDBC

How to start an IMMEDIATE TRANSACTION in SQLITE JDBC

我在使用 JDBC 进行交易时遇到了一点问题。 我想开始一个 IMMEDIATE 交易,它在 SQL 中是:

BEGIN IMMEDIATE;

在 Java JDBC SQLite 中,您不能这样做。如果启用了自动提交,则不能在语句上调用 BEGIN IMMEDIATE。提交查询将导致“自动提交已启用”错误。

 db = DriverManager.getConnection("jdbc:sqlite:sqlite.db");

 // start a transaction using an sql query...
 db.createStatement().execute("BEGIN IMMEDIATE");

 // create another statement because this is running from another method...
 stmt = db.createStatement();
 stmt.executeUpdate("UPDATE table SET column='value' WHERE id=1");

 // this will cause an error(exception): AUTOCOMMIT IS ENABLED.
 db.commit();

上面的代码将抛出一个 AUTOCOMMIT IS ENABLED 异常。

但是,禁用自动提交时也会出现问题,因为它会在使用该代码后启动事务。考虑以下代码:

db = DriverManager.getConnection("jdbc:sqlite:ez-inventory.db");
// doing the createstatement and setautocommit reciprocally still produce the same exception.
db.setAutoCommit(false);
db.createStatement().execute("BEGIN IMMEDIATE");

此代码将抛出另一个异常:

[SQLITE_ERROR] SQL error or missing database (cannot start a transaction within a transaction)

连接中有一个 setTransactionIsolation 方法,但它不是用于事务锁定。是为了隔离。我需要使用任何 SQLite 交易模式开始交易:DEFFEREDIMMEDIATEEXCLUSIVE

SQLite JDBC 这可能吗?

好的,我知道了!您应该使用 transaction_mode 键和所需的事务模式值创建一个 Properties 对象。并在创建新的 SQL Connection 实例时将 Properties 对象作为参数。

import java.sql.*; // <-- bad practice.. just too lazy to put the needed modules one by one for this example

public void immediate_transaction_example() throws SQLException {

    // create a properties with a transaction_mode value
    Properties sqlprop = new Properties();
    properties.put("transaction_mode", "IMMEDIATE"); // <-- can be DEFERRED, IMMEDIATE, or EXCLUSIVE


    db = new DriverManager.getConection("jdbc:sqlite:sqlite.db", sqlprop); // <-- pass the properties to the new sql connection instance.
    db.setAutoCommit(false); // <-- this will automatically begin the transaction with the specified transaction mode...
    // other new transactions attempts with immediate transaction mode will be blocked until the connection is closed.
    try {
        // proceed the transactions here...
        db.createStatement().execute("INSERT INTO table (id, value) VALUES (1, 'myvalue')");
        db.createStatement().execute("INSERT INTO table (id, value) VALUES (2, 'myvalue')");

        // no errors proceed
        db.commit();
    } catch (SQLException ex) {
        // there is an error!
        db.rollback();
    }
    db.close() // <-- you need to close the connection for sqlite to create a new immediate transaction.
}

注意:这里使用了xerial的sqlite-jdbc模块。

模块 Link:https://github.com/xerial/sqlite-jdbc