如何在 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 交易模式开始交易:DEFFERED
、IMMEDIATE
或 EXCLUSIVE
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模块。
我在使用 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 交易模式开始交易:DEFFERED
、IMMEDIATE
或 EXCLUSIVE
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模块。