Java 如何使用JDBC在一个事务中执行2个更新查询

Java 如何使用JDBC在一个事务中执行2个更新查询,java,mysql,jdbc,Java,Mysql,Jdbc,我是JDBC新手,我正在尝试更新数据库中的两个表,所以我希望在一个事务中完成这项工作,因此如果一个查询失败,另一个也应该失败。我希望提供这样的行为,或者在其中一个失败时有机会执行回滚 以下是我的两个问题: int i = stmt.executeUpdate("INSERT INTO product (title, price, `status`) " + "VALUES ( \"" + product.getTitle() + "\", " + product.

我是JDBC新手,我正在尝试更新数据库中的两个表,所以我希望在一个事务中完成这项工作,因此如果一个查询失败,另一个也应该失败。我希望提供这样的行为,或者在其中一个失败时有机会执行回滚

以下是我的两个问题:

int i = stmt.executeUpdate("INSERT INTO product (title, price, `status`) " +
                "VALUES ( \"" + product.getTitle() + "\", " + product.getPrice() + ", " + product.getStatus().ordinal() + ");");
int j = stmt.executeUpdate("INSERT INTO product_categories (product_id, category_id) " +
                "VALUES (last_insert_id(), " + categoryId + ");");

如果希望原子地执行多个语句,则需要使用事务。JDBC连接默认为“自动提交”模式,这意味着每个语句都在自己的事务中执行。因此,首先需要使用禁用自动提交模式

禁用自动提交模式时,将在当前事务中执行已执行语句,如果没有当前事务,将启动一个。然后可以使用提交或使用回滚此事务

您需要执行以下操作:

try (Connection connection = DriverManager.getConnection(...)) {
    connection.setAutoCommit(false);
    try (Statement stmt = connection.createStatement()) {
        stmt.executeUpdate(<your first update>);
        stmt.executeUpdate(<your second update>);

        connection.commit();
    } catch (SQLException e) {
        connection.rollback();
        throw e;
    }
}
try(Connection-Connection=DriverManager.getConnection(…){
connection.setAutoCommit(false);
try(语句stmt=connection.createStatement()){
stmt.executeUpdate();
stmt.executeUpdate();
commit();
}捕获(SQLE异常){
connection.rollback();
投掷e;
}
}
有关更多详细信息,请参阅JDBC教程一章


请了解准备好的声明。将值串联到查询字符串中是不好的,因为如果忘记转义值,可能会导致SQL注入或奇怪的错误。另请参见JDBC教程章节。

这一行“connection.setAutoCommit(false);”应该在try-catch块中。另外,一个好的做法是在finally块中添加“con.setAutoCommit(true);”。@Maksymovsiankov不,不需要这样做,除非您想将自动提交恢复为true。你为什么认为这是必需的?请允许我提醒您,这是一个简单的示例,不是一个完整的实际应用。@Mark Rotterveel,我没有写它是必需的,我写它是“一个好的实践”:)检查Oracle教程:这是一个很好的答案!我认为最好还提到数据库需要设置为特定的隔离级别。例如,如果将Postgres设置为“Read uncommitted”隔离级别,那么在提交事务之前,查询实际上可以看到插入的产品,这将违反大多数用户对原子性的期望。