• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录

奋斗的软件工程师

  • 博客园
  • 联系
  • 订阅
  • 管理

公告

View Post

使用JDBC控制事务:确保数据一致性

使用JDBC控制事务:确保数据一致性

在Java中,JDBC(Java Database Connectivity)是用于连接和操作数据库的标准API。事务管理是JDBC中的一个重要功能,确保数据库操作的一致性和完整性。本文将详细介绍如何使用JDBC控制事务,并通过一个实际案例演示如何处理事务中的异常情况,确保数据的一致性。

1. 事务管理的重要性

事务是一组数据库操作,这些操作要么全部成功执行,要么全部失败回滚。事务管理确保了数据的一致性和完整性,避免了部分操作成功而部分操作失败导致的数据不一致问题。

在JDBC中,事务管理通过以下步骤实现:

  1. 开启事务:将自动提交模式设置为false,手动控制事务的提交和回滚。

    connection.setAutoCommit(false); // 开启手动控制事务
    
  2. 执行SQL操作:执行一系列的SQL语句。

    resultSet = statement.executeQuery(sql);
    
  3. 提交事务:如果所有操作都成功,提交事务。

    connection.commit(); // 提交事务
    
  4. 回滚事务:如果某个操作失败,回滚事务,撤销所有已执行的操作。

    connection.rollback(); // 回滚事务
    

2. 事务管理的代码示例

我的数据库里面创建了1张表

create table tb_transaction (
  id    int primary key auto_increment,
  name  varchar(32) unique not null,
  money double(7, 2)
);

insert into tb_transaction values(1,'a',1000),(2,'b',1000);

我向表中插入了2条数据,以下是一个使用JDBC控制事务的代码示例(错误示例),演示了如何执行一系列的UPDATE操作,并在操作失败时回滚事务。

package b_jdbc;

import java.sql.*;

public class App {
    public static void main(String[] args) {

        String sql = null;

        Connection connection = null;
        Statement statement = null;
        ResultSet resultSet = null;

        try {
            connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3309/db_transaction", "root", "928151");
            statement = connection.createStatement();
            connection.setAutoCommit(false); // 开启手动控制事务

            sql = "UPDATE tb_transaction SET money = money + 100 WHERE name='a'";
            statement.executeUpdate(sql);
c
            sql = "UPDATE tb_transaction SET money = money - 100 WHERE name='c'";
            statement.executeUpdate(sql);

            sql = "SELECT * FROM tb_transaction";
            resultSet = statement.executeQuery(sql);
            
            while (resultSet.next()) {
                int id = resultSet.getInt(1);
                String name = resultSet.getString(2);
                double money = resultSet.getDouble(3);
                System.out.println(id + "---" + name + "---" + money);
            }

            connection.commit(); // 提交事务
        } catch (Exception e) {
            e.printStackTrace();
            try {
                if (connection != null) {
                    connection.rollback(); // 回滚事务
                }
            } catch (SQLException e1) {
                e1.printStackTrace();
            }
        } finally {
            try {
                if (resultSet != null) {
                    resultSet.close();
                }
                if (statement != null) {
                    statement.close();
                }
                if (connection != null) {
                    connection.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

3. 错误案例分析

在实际开发中,可能会遇到以下错误案例:

sql = "UPDATE tb_transaction SET money = money + 100 WHERE name='a'";
int i1 = statement.executeUpdate(sql);

sql = "UPDATE tb_transaction SET money = money - 100 WHERE name='c'";
int i2 = statement.executeUpdate(sql);

在这个案例中,name='c'不存在,executeUpdate()方法会返回0,但不会抛出异常。这可能导致事务的一致性问题,因为name='a'的money会增加100,而name='b'的money不会减少100。这显然违反了事务的一致性原则。

4. 解决方案

1.为了确保事务的一致性,可以在执行UPDATE操作前,先验证记录是否存在。如果记录不存在,抛出异常并回滚事务。

2.为了确保事务的一致性,可以在执行UPDATE操作后检查executeUpdate()的返回值。如果返回值为0,说明没有找到匹配的记录,应该抛出异常并回滚事务。

4.1验证记录是否存在
4.1.1

在执行UPDATE操作前,先执行SELECT COUNT(*)查询,验证记录是否存在。如果记录不存在,抛出异常并回滚事务。

// 先验证name='a'是否存在
sql = "SELECT COUNT(*) FROM tb_transaction WHERE name='a'";
resultSet = statement.executeQuery(sql);
resultSet.next();
int countA = resultSet.getInt(1);
if (countA == 0) {
    throw new SQLException("name='a'不存在");
}

sql = "UPDATE tb_transaction SET money = money + 100 WHERE name='a'";
int i1 = statement.executeUpdate(sql);

// 先验证name='b'是否存在
sql = "SELECT COUNT(*) FROM tb_transaction WHERE name='b'";
resultSet = statement.executeQuery(sql);
resultSet.next();
int countB = resultSet.getInt(1);
if (countB == 0) {
    throw new SQLException("name='b'不存在");
}

sql = "UPDATE tb_transaction SET money = money - 100 WHERE name='b'";
int i2 = statement.executeUpdate(sql);

4.1.2

为了确保事务的一致性,可以在执行UPDATE操作后检查executeUpdate()的返回值。如果返回值为0,说明没有找到匹配的记录,应该抛出异常并回滚事务。

sql = "UPDATE tb_transaction SET money = money + 100 WHERE name = 'a'";
int i1 = statement.executeUpdate(sql);
if (i1 == 0) {
    throw new SQLException("No rows affected by the first update operation.");
}

sql = "UPDATE tb_transaction SET money = money - 100 WHERE name = 'b'";
int i2 = statement.executeUpdate(sql);
if (i2 == 0) {
	throw new SQLException("No rows affected by the second update operation.");
}
4.2 回滚事务

在捕获异常后,执行connection.rollback()方法回滚事务,确保数据的一致性。

catch (Exception e) {
    e.printStackTrace();
    try {
        if (connection != null) {
            connection.rollback(); // 回滚事务
        }
    } catch (SQLException e1) {
        e1.printStackTrace();
    }
}

5. 总结

  • 事务一致性:确保事务中的所有操作要么全部成功,要么全部失败。
  • 验证记录:在执行UPDATE操作前,先验证记录是否存在。如果记录不存在,抛出异常并回滚事务。
  • 回滚事务:在捕获异常后,执行connection.rollback()方法回滚事务,确保数据的一致性。

通过以上改进,可以确保事务的一致性,避免数据不一致的问题。在实际开发中,事务管理是确保数据一致性和完整性的重要手段,开发者应充分理解和掌握JDBC中的事务管理机制。

posted on 2024-11-23 18:39  周政然  阅读(122)  评论(0)    收藏  举报

刷新页面返回顶部
 
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3