JDBC 控制事务(MySQL为例)

事务

一个包含多个步骤的业务操作。如果这个业务操作被事务管理,则这多个步骤要么同时成功,要么同时失败。

对事务的操作

  1. 开启事务
  2. 提交事务
  3. 回滚事务

使用Connection对象来管理事务

java.sql.Connection接口是一个数据库连接对象。它与特定数据库的连接(会话)。 执行SQL语句并在连接的上下文中返回结果。

  • 开启事务

    setAutoCommit(boolean autoCommit)
    // 调用该方法设置参数为false,即开启事务
  • 提交事务

    commit()
    // 当所有sql都执行完提交事务
  • 回滚事务

    rollback()
    // 在catch中回滚事务

Java代码举例

有如下一个MySQL数据表,利用Java程序:把id = 1对应的余额减少500,id = 2对应的余额增加500

CREATE TABLE account (
    id INT PRIMARY KEY AUTO_INCREMENT,   -- id
    NAME VARCHAR(10),                    -- 名字
    balance DOUBLE                       -- 余额
);

INSERT INTO account (NAME, balance) VALUES (‘LeeHua‘, 1000), (‘Tom‘, 1000);

自定义一个注解,获取连接数据库的信息:

package my.view.util;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.TYPE) // 注解能作用于类上
@Retention(RetentionPolicy.RUNTIME) // 当前被描述的注解,会保留到class字节码文件中,并被JVM读取到
public @interface PropertiesAnnotation {

    /* URL */
    public abstract String url();

    /* 用户 */
    public abstract String user();

    /* 密码 */
    public abstract String password();

    /* 驱动包 */
    public abstract String driver();
}

定义一个工具类,用来注册驱动和获取数据库连接对象:

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

@PropertiesAnnotation(
        url = "jdbc:mysql:///Study", user = "账号", password = "密码", driver = "com.mysql.jdbc.Driver"
)
public class JdbcUtils02 {

    private static String url;
    private static String user;
    private static String password;
    private static String driver;

    /* 文件的读取,只需要读取一次即可拿到这些值。利用反射和注解、使用静态代码块 */
    static{
        // 读取资源文件,获取值。

        try {
            // 1. 解析注解
            // 1.1 获取JdbcUtils02类的字节码文件对象
            Class<JdbcUtils02> jdbcUtils02Class = JdbcUtils02.class;

            // 2. 获取上边的注解对象
            PropertiesAnnotation annotation = jdbcUtils02Class.getAnnotation(PropertiesAnnotation.class);

            // 3. 调用注解中定义的抽象方法,获取返回值,赋值给静态成员变量
            url = annotation.url();
            user = annotation.user();
            password = annotation.password();
            driver = annotation.driver();

            // 4. 注册驱动
            Class.forName(driver);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取连接
     * @return 连接对象
     */
    public static Connection getConnection() throws SQLException {
        return DriverManager.getConnection(url, user, password);
    }

}

有了以上条件,对数据表进行操作:

  1. 获取数据库连接

    Connection connection = JdbcUtils02.getConnection();
  2. 获取到数据库连接对象后,开启事务

    connection.setAutoCommit(false);
  3. 开启事务实际上是创建一个日志文件,将定义的SQL语句的执行结果暂时放到日记中,如果没有错,提交事务,如果出错,那么就回滚事务。接下来定义动态SQL语句

    String sql1 = "update account set balance = balance - ? where id = ?";
    String sql2 = "update account set balance = balance + ? where id = ?";
  4. 定义好了SQL语句,接下来就要获取执行动态SQL语句的对象

    PreparedStatement preparedStatement1 = connection.prepareStatement(sql1);
    
    PreparedStatement preparedStatement2 = connection.prepareStatement(sql2);
  5. 给动态SQL语句传入参数

    // LeeHua 的账户余额减少500元
    preparedStatement1.setDouble(1,500);
    preparedStatement1.setInt(2,1);
    
    // Tom 的账户余额增加500元
    preparedStatement2.setDouble(1,500);
    preparedStatement2.setInt(2,2);
  6. 一切准备就绪,这时候就可以执行SQL语句了

    preparedStatement1.executeUpdate();
    preparedStatement2.executeUpdate();
  7. 执行SQL语句后,如果没有错误,那么就提交事务,这时候的表记录就会更改

    connection.commit();
  8. 执行SQL语句后,如果有错误,那么就回滚事务,这个时候,会把日记中的记录删除,不会提交到表中,表的记录不会更改

    connection.rollback();
  9. 无论执行SQL语句,是否存在错误,最后都需要释放资源,调用自定义releaseResources()方法,释放资源

    releaseResources(preparedStatement2);
    releaseResources(preparedStatement1);
    releaseResources(connection);
  10. releaseResources()方法的定义如下:

    /**
     * 释放资源
     * @param t 要被释放的资源
     * @param <T> 要被释放的资源对象的类型
     */
    public static <T> void releaseResources (T t){
        if(t != null){
            try {
                // 利用反射,获取class对象
                Class<?> aClass = t.getClass();
                // 获取class对象中的方法对象
                Method close = aClass.getMethod("close");
                // 执行方法
                close.invoke(t);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

对数据表进行操作的实现代码如下:

package my.view.jdbc;

import my.view.util.JdbcUtils02;

import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

public class JdbcDemo09 {

    public static void main(String[] args) {
        Connection connection = null;
        PreparedStatement preparedStatement1 = null;
        PreparedStatement preparedStatement2 = null;

        try {
            // 1. 获取连接
            connection = JdbcUtils02.getConnection();

            // 开启事务
            connection.setAutoCommit(false);

            // 2. 定义sql
            // 2.1 定义减少账户余额的SQL语句
            String sql1 = "update account set balance = balance - ? where id = ?";
            // 2.2 定义增加账户余额的SQL语句
            String sql2 = "update account set balance = balance + ? where id = ?";

            // 3.获取执行SQL语句的对象
            preparedStatement1 = connection.prepareStatement(sql1);
            preparedStatement2 = connection.prepareStatement(sql2);

            // 4. 设置参数
            // 4.1 LeeHua 的账户余额减少500元
            preparedStatement1.setDouble(1,500);
            preparedStatement1.setInt(2,1);
            // 4.2 Tom 的账户余额增加500元
            preparedStatement2.setDouble(1,500);
            preparedStatement2.setInt(2,2);

            // 5. 执行SQL语句
            preparedStatement1.executeUpdate();
            preparedStatement2.executeUpdate();

            // 6. 提交事务
            connection.commit();
        } catch (Exception e) {
            // 7. 事务回滚
            try {
                if(connection != null) {
                    connection.rollback();
                }
            } catch (SQLException e1) {
                e1.printStackTrace();
            }
        } finally {
            // 8. 释放资源
            releaseResources(preparedStatement2);
            releaseResources(preparedStatement1);
            releaseResources(connection);
        }

    }

    /**
     * 释放资源
     * @param t 要被释放的资源
     * @param <T> 要被释放的资源对象的类型
     */
    public static <T> void releaseResources (T t){
        if(t != null){
            try {
                // 利用反射,获取class对象
                Class<?> aClass = t.getClass();
                // 获取class对象中的方法对象
                Method close = aClass.getMethod("close");
                // 执行方法
                close.invoke(t);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

}

运行程序,查看表中的记录,发现LeeHua的账号余额减少了500,Tom的账户余额增加了500。

原文地址:https://www.cnblogs.com/liyihua/p/12324613.html

时间: 2024-07-30 13:34:58

JDBC 控制事务(MySQL为例)的相关文章

JDBC数据库连接(MySQL为例)

1.什么是JDBC?有什么作用? Java Data Base Connectivity  Java数据库连接协议 是一种用于执行SQL语句的Java API,可以为多种关系数据库提供统一访问. 他提供了一种基准,据此可以构建更高级的工具和接口,使开发人员能够编写数据库应用程序 有了JDBC, 向各种关系数据发送sql语句就变得很容易了 换句话说就是有了JDBC API就不用为了访问Oracle数据库专门写一个程序 或者又为访问MySQL数据库专门写一个程序. 2.Java APP使用JDBC连

通过JDBC进行简单的增删改查(以MySQL为例) 目录

通过JDBC进行简单的增删改查(以MySQL为例) 目录 前言:什么是JDBC 一.准备工作(一):MySQL安装配置和基础学习 二.准备工作(二):下载数据库对应的jar包并导入 三.JDBC基本操作 (1)定义记录的类(可选) (2)连接的获取 (3)insert (4)update (5)select (6)delete 四.测试 五.代码分析 六.思考问题 前言:什么是JDBC 维基百科的简介: Java 数据库连接,(Java Database Connectivity,简称JDBC)

MySql命令行控制事务

新建表t1 CREATE TABLE `t1` (   `a` int(11) NOT NULL,   `b` int(11) DEFAULT NULL,   PRIMARY KEY (`a`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1; 查看mysql系统级别的事务隔离级别: mysql> SELECT @@global.tx_isolation; +-----------------------+ | @@global.tx_isolation | +--

Java通过JDBC进行简单的增删改查(以MySQL为例)

Java通过JDBC进行简单的增删改查(以MySQL为例) 目录: 前言:什么是JDBC 一.准备工作(一):MySQL安装配置和基础学习 二.准备工作(二):下载数据库对应的jar包并导入 三.JDBC基本操作   (1)定义记录的类(可选) (2)连接的获取 (3)insert (4)update (5)select (6)delete 四.测试 五.代码分析 六.思考问题 前言:什么是JDBC 维基百科的简介: Java 数据库连接,(Java Database Connectivity,

Net Core中数据库事务隔离详解——以Dapper和Mysql为例

Net Core中数据库事务隔离详解--以Dapper和Mysql为例 事务隔离级别 准备工作 Read uncommitted 读未提交 Read committed 读取提交内容 Repeatable read (可重读) Serializable 序列化 总结 事务隔离级别 .NET Core中的IDbConnection接口提供了BeginTransaction方法作为执行事务,BeginTransaction方法提供了两个重载,一个不需要参数BeginTransaction()默认事务

JDBC 入门 - 事务

Transaction(事务) 事务简介 事务的作用是保护数据完整性.它将一系列操作作为一个原子操作来处理, 从而防止多个操作中有的操作失败有的操作成功, 造成数据不完整. 在 JDBC 中, 一个连接默认的提交方式是 Auto-Commit 模式, 在这种模式下, 每个单独的SQL语句都会被视为一个事务, 当SQL执行时(更确切的说是完成时,详见 这里), 就会被提交到数据库. 然而, 在要求多个 SQL 同时成功或者失败的数据完整性问题时, 这种模式不能满足需要. 禁用 Auto-Commi

【JDBC】事务的使用

转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/5868750.html 关于事务的理论知识.ACID特性等等,网上太多了,在此不一一重复.本文主要着重  事务  这个工具在实际编程中是怎么实现的. 在MySQL命令行的默认设置下,事务都是自动提交的,即执行SQL语句后就会马上执行COMMIT操作,每一个SQL语句都被认为是一个完整的事务处理. 而我们想要实现事务,即:执行多句SQL语句,再最终一起提交或在出错时撤销(SQL语句要么提交,要么撤销.提交则对数

Java中JDBC的事务问题

事务 l  事务的四大特性:ACID: l  mysql中操作事务 l  jdbc中操作事务 事务概述 为了方便演示事务,我们需要创建一个account表: CREATE TABLE account(          id INT PRIMARY KEY AUTO_INCREMENT,          NAME VARCHAR(30),          balance NUMERIC(10.2) );   INSERT INTO account(NAME,balance) VALUES('

JDBC实现往MySQL插入百万级数据

from:http://www.cnblogs.com/fnz0/p/5713102.html JDBC实现往MySQL插入百万级数据 想往某个表中插入几百万条数据做下测试, 原先的想法,直接写个循环10W次随便插入点数据试试吧,好吧,我真的很天真.... DROP PROCEDURE IF EXISTS proc_initData;--如果存在此存储过程则删掉 DELIMITER $ CREATE PROCEDURE proc_initData() BEGIN DECLARE i INT DE