我的应用程序只有Java和Maven(没有其他框架)
在pom.xml中,我对H2数据库有依赖性:
<dependencies>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.4.199</version>
</dependency>
</dependencies>
我以这种方式创建了一个连接,您可以看到我将autocommit设置为false。并且我的H2数据库在内存中。
public class ConnectionManager {
public static Connection getConnectionManager() throws SQLException {
Properties myProp = new Properties();
myProp.put("user" , "sa");
myProp.put("password", "");
myProp.put("autocommit", "false");
return DriverManager.getConnection("jdbc:h2:mem:test", myProp);
}
public static void closeConnection(Connection connection) throws SQLException {
connection.close();
}
}
我创建了示例表:
public class InitDatabaseManager {
private static final String CREATE_TABLE_SQL =
"CREATE TABLE IF NOT EXISTS users ("
+ "ID INT NOT NULL AUTO_INCREMENT,"
+ "EMAIL VARCHAR(45) NOT NULL,"
+ "PRIMARY KEY (ID))";
private static final String DROP_TABLE_USERS = "drop table if exists users;";
public static void initStarterTable (Connection connection) throws SQLException {
Statement stmt = connection.createStatement();
stmt.executeUpdate(DROP_TABLE_USERS);
stmt.executeUpdate(CREATE_TABLE_SQL);
}
}
我的问题是,为什么在下面的代码中,尽管我禁用了自动提交,但我还是插入了H2数据库中的记录?
public static void insertUsers(Connection connection) throws SQLException {
connection.setAutoCommit(false);
System.out.println("[INSERT]");
String sqlInsert1 = "INSERT INTO users (email) VALUES ('user@mail.com');";
PreparedStatement psInsert = connection.prepareStatement(sqlInsert1);
System.out.println(connection.getAutoCommit());
psInsert.execute();
psInsert.close();
}
答案 0 :(得分:0)
执行INSERT
命令时,它会将指定的行插入到表中。该行仅对执行此操作的事务可见,而对其他事务(如果它们使用默认的“读取已提交”隔离级别)则不可见。在隐式(由于自动提交)或显式手动提交之后,插入的行对于所有事务都是可见的。如果您回滚事务而不是提交,则该行会消失。
其他数据修改操作以相同的方式工作。未提交的更改仅对执行它们的事务可见,已提交的更改对所有人可见。
交易的隔离级别不同,但是H.2的默认存储引擎在1.4.199中尚不支持它们(1.4.200中包含这种支持)。
每个JDBC连接都有自己的会话,并且这个会话有自己的事务。我猜您使用相同的连接来读取插入的数据,因此它可以看到未提交的行。如果您不想看到它们,请使用其他连接。
H2中的数据定义命令(例如CREATE TABLE
)通常会导致隐式提交,有关详细信息,请参阅H2文档。
答案 1 :(得分:0)
我添加了两个连接,然后更改了隔离级别,我的问题是为什么第二个事务看不到由第一个事务完成的更改。第一个事务未提交更改,因此,如果事务隔离级别为TRANSACTION_READ_UNCOMMITTED,则第二个事务应已看到第一个事务的更改。
我知道:
H2仅支持三个隔离级别;读未提交,读已提交和可序列化,只能在连接级别设置(不能按事务设置)。默认值为已提交读。public class StartUseCases {
private static Connection connection;
private static Connection connection2;
public StartUseCases() {
try {
connection = ConnectionManager.getConnectionManager();
connection.setAutoCommit(false);
connection.setTransactionIsolation(Connection.TRANSACTION_READ_UNCOMMITTED);
connection2 = ConnectionManager.getConnectionManager();
connection2.setAutoCommit(false);
connection2.setTransactionIsolation(Connection.TRANSACTION_READ_UNCOMMITTED);
InitDatabaseManager.initStarterTable(connection);
} catch (SQLException e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws SQLException {
// init tables
new StartUseCases();
CRUD.getAllUsers(connection);
CRUD.insertUsers(connection2);
CRUD.getAllUsers(connection);
}
}