java:JDBC

What is JDBC

We know that there are many kinds of databases, such as mysql, Oracle, DB2, etc. If the operation methods of each database are different, it will be very uncomfortable, so java provides a specification for each database manufacturer to follow this specification. It is a set of jar packages, and the java code only needs to write the same set of code (JDBC) to be compatible with all databases.

One sentence summary: java expects to use a unified set of java code to operate all relational databases
insert image description here

JDBC usage steps

  1. Import the driver jar package mysql-connector-java-5.1.37-bin.jar
    1.1. Copy mysql-connector-java-5.1.37-bin.jar to the libs directory of the project
    1.2. Right-click –> Add As Library
  2. register driver
  3. Get the database connection object Connection
  4. define sql
  5. Obtain the object Statement that executes the sql statement
  6. Execute sql and accept the returned result
  7. process result
  8. release resources
package cn.itcast.jdbc;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;

/**
 * JDBC快速入门
 */
public class JdbcDemo1 {
    
    
    public static void main(String[] args) throws Exception {
    
    

        //1. 导入驱动jar包
        //2. 注册驱动(可省略)
        // Class.forName("com.mysql.jdbc.Driver");
        //3. 获取数据库连接对象
		// Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/db3", "root", "root");
        Connection conn = DriverManager.getConnection("jdbc:mysql:///db3", "root", "root");
        //4. 定义sql语句
		// String sql = "update account set balance = 2000 where id = 1";
        String sql = "update account set balance = 2000";
        //5. 获取执行sql的对象 Statement
        Statement stmt = conn.createStatement();
        //6. 执行sql
        int count = stmt.executeUpdate(sql);
        //7. 处理结果
        System.out.println(count);
        //8. 释放资源
        stmt.close();
        conn.close();

    }
}

In the above code, we can see that there are several SQL-related objects:

  1. DriverManager
  2. Connection
  3. Statement
  4. ResultSet
  5. PreparedStatement

Next, we explain each object in detail

Explain each object in detail

DriverManager

It is a driver management object, and its functions are:
1. Register driver: Tell the program which database driver jar to use.
The embodiment of registering the driver in the code is this sentence: Class.forName("com.mysql.jdbc.Driver");, but why is this sentence registering the driver?

// 通过查看源码发现:在com.mysql.jdbc.Driver类中存在静态代码块
static {
    
    
      try {
    
    
      	  // 这个才是真正的注册驱动
          java.sql.DriverManager.registerDriver(new Driver());
      } catch (SQLException E) {
    
    
          throw new RuntimeException("Can't register driver!");
      }
}

Note: The driver jar package after mysql5 can omit the step of registering the driver.

2. Get the database connection:

  • method:static Connection getConnection(String url, String user, String password)
  • parameter:
    • url: specify the path of the connection
      • grammar:jdbc:mysql://ip地址(域名):端口号/数据库名称
      • example:jdbc:mysql://localhost:3306/db3
      • Details: If you are connecting to the local mysql server, and the default port of the mysql service is 3306, the url can be abbreviated as: jdbc:mysql:///database name
    • user: username
    • password: password

Connection

Database connection object, function:

1. 获取执行sql 的对象
	* Statement createStatement()
	* PreparedStatement prepareStatement(String sql)  
2. 管理事务:
	* 开启事务:setAutoCommit(boolean autoCommit) :调用该方法设置参数为false,即开启事务
	* 提交事务:commit() 
	* 回滚事务:rollback() 

Statement

The object to execute sql.
Function 1: execute sql

  1. boolean execute(String sql) : Can execute arbitrary sql (if you understand it, you can not use it often)
  2. int executeUpdate(String sql): Execute DML (insert, update, delete) statements, DDL (create, alter, drop) statements. Return value: the number of rows affected, you can use the number of rows affected to judge whether the DML statement is executed successfully. If the return value is >0, the execution is successful, otherwise, it fails.
  3. ResultSet executeQuery(String sql): Execute DQL (select) statement

practise:

  1. Add a record to the account table
  2. account table modification record
  3. Account table deletes a record
package cn.xxx.jdbc;

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

/**
 * account表 添加一条记录 insert 语句
 */
public class JDBCDemo2 {
    
    
    public static void main(String[] args) {
    
    
        Statement stmt = null;
        Connection conn = null;
        try {
    
    
            //1. 注册驱动
            Class.forName("com.mysql.jdbc.Driver");
            //2. 定义sql
            // String sql  = "update account set balance = 1500 where id = 3";
            // String sql  = "delete from account where id = 3";
            String sql = "insert into account values(null,'王五',3000)";
            //3.获取Connection对象
            conn = DriverManager.getConnection("jdbc:mysql:///db3", "root", "root");
            //4.获取执行sql的对象 Statement
            stmt = conn.createStatement();
            //5.执行sql
            int count = stmt.executeUpdate(sql);//影响的行数
            //6.处理结果
            System.out.println(count);
            if(count > 0){
    
    
                System.out.println("添加成功!");
            }else{
    
    
                System.out.println("添加失败!");
            }

        } catch (ClassNotFoundException e) {
    
    
            e.printStackTrace();
        } catch (SQLException e) {
    
    
            e.printStackTrace();
        }finally {
    
    
            //stmt.close();
            //7. 释放资源
            //避免空指针异常
            if(stmt != null){
    
    
                try {
    
    
                    stmt.close();
                } catch (SQLException e) {
    
    
                    e.printStackTrace();
                }
            }

            if(conn != null){
    
    
                try {
    
    
                    conn.close();
                } catch (SQLException e) {
    
    
                    e.printStackTrace();
                }
            }
        }
    }
}

ResultSet

The result set object encapsulates the query results.

  • boolean next(): Move the cursor down one line, judge whether the current line is the end of the last line (whether there is data), if yes, return false, otherwise return true

  • getXxx (parameter): get data

    • Xxx: Represents data types such as: int getInt() , String getString()
    • parameter:
      1. int: represents the number of the column, starting from 1 such as: getString(1)
      2. String: Represents the column name. Such as: getDouble("balance")
  • Notice:

    • Steps for usage:
      1. Move the cursor down one line
      2. Determine whether there is data
      3. retrieve data
//循环判断游标是否是最后一行末尾。
while(rs.next()){
    
    
    //获取数据
    //6.2 获取数据
    int id = rs.getInt(1);
    String name = rs.getString("name");
    double balance = rs.getDouble(3);

    System.out.println(id + "---" + name + "---" + balance);
}

basic use

package cn.xxx.jdbc;

import java.sql.*;

/**
 * 执行DDL语句
 */
public class JDBCDemo6 {
    
    
    public static void main(String[] args) {
    
    
        Connection conn = null;
        Statement stmt = null;
        ResultSet rs = null;
        try {
    
    
            //1. 注册驱动
            Class.forName("com.mysql.jdbc.Driver");
            //2.获取连接对象
            conn = DriverManager.getConnection("jdbc:mysql:///db3", "root", "root");
            //3.定义sql
            String sql  = "select * from account";
            //4.获取执行sql对象
            stmt = conn.createStatement();
            //5.执行sql
            rs = stmt.executeQuery(sql);
            //6.处理结果
            //6.1 让游标向下移动一行
            rs.next();
            //6.2 获取数据
            int id = rs.getInt(1);
            String name = rs.getString("name");
            double balance = rs.getDouble(3);

            System.out.println(id + "---" + name + "---" + balance);


            //6.1 让游标向下移动一行
            rs.next();
            //6.2 获取数据
            int id2 = rs.getInt(1);
            String name2 = rs.getString("name");
            double balance2 = rs.getDouble(3);

            System.out.println(id2 + "---" + name2 + "---" + balance2);

            //6.1 让游标向下移动一行
            rs.next();
            //6.2 获取数据
            int id3 = rs.getInt(1);
            String name3 = rs.getString("name");
            double balance3 = rs.getDouble(3);

            System.out.println(id3 + "---" + name3 + "---" + balance3);


        } catch (ClassNotFoundException e) {
    
    
            e.printStackTrace();
        } catch (SQLException e) {
    
    
            e.printStackTrace();
        } finally {
    
    
            //7.释放资源

            if(rs != null){
    
    
                try {
    
    
                    rs.close();
                } catch (SQLException e) {
    
    
                    e.printStackTrace();
                }
            }

            if(stmt != null){
    
    
                try {
    
    
                    stmt.close();
                } catch (SQLException e) {
    
    
                    e.printStackTrace();
                }
            }

            if(conn != null){
    
    
                try {
    
    
                    conn.close();
                } catch (SQLException e) {
    
    
                    e.printStackTrace();
                }
            }
        }
    }

}

Optimized use

package cn.itcast.jdbc;

import java.sql.*;

/**
 * 执行DDL语句
 */
public class JDBCDemo7 {
    
    
    public static void main(String[] args) {
    
    
        Connection conn = null;
        Statement stmt = null;
        ResultSet rs = null;
        try {
    
    
            //1. 注册驱动
            Class.forName("com.mysql.jdbc.Driver");
            //2.获取连接对象
            conn = DriverManager.getConnection("jdbc:mysql:///db3", "root", "root");
            //3.定义sql
            String sql  = "select * from account";
            //4.获取执行sql对象
            stmt = conn.createStatement();
            //5.执行sql
            rs = stmt.executeQuery(sql);
            //6.处理结果
            //循环判断游标是否是最后一行末尾。
            while(rs.next()){
    
    

                //获取数据
                //6.2 获取数据
                int id = rs.getInt(1);
                String name = rs.getString("name");
                double balance = rs.getDouble(3);

                System.out.println(id + "---" + name + "---" + balance);
            }


           /* //6.1 让游标向下移动一行
            if(rs.next()){
                //判断是否有数据
                //6.2 获取数据
                int id = rs.getInt(1);
                String name = rs.getString("name");
                double balance = rs.getDouble(3);

                System.out.println(id + "---" + name + "---" + balance);
            }

            //6.1 让游标向下移动一行
            if(rs.next()){
                //判断是否有数据
                //6.2 获取数据
                int id = rs.getInt(1);
                String name = rs.getString("name");
                double balance = rs.getDouble(3);

                System.out.println(id + "---" + name + "---" + balance);
            }

            //6.1 让游标向下移动一行
            if(rs.next()){
                //判断是否有数据
                //6.2 获取数据
                int id = rs.getInt(1);
                String name = rs.getString("name");
                double balance = rs.getDouble(3);

                System.out.println(id + "---" + name + "---" + balance);
            }

            //6.1 让游标向下移动一行
            if(rs.next()){
                //判断是否有数据
                //6.2 获取数据
                int id = rs.getInt(1);
                String name = rs.getString("name");
                double balance = rs.getDouble(3);

                System.out.println(id + "---" + name + "---" + balance);
            }*/

          /*  //6.1 让游标向下移动一行
            rs.next();
            //6.2 获取数据
            int id2 = rs.getInt(1);
            String name2 = rs.getString("name");
            double balance2 = rs.getDouble(3);

            System.out.println(id2 + "---" + name2 + "---" + balance2);

            //6.1 让游标向下移动一行
            rs.next();
            //6.2 获取数据
            int id3 = rs.getInt(1);
            String name3 = rs.getString("name");
            double balance3 = rs.getDouble(3);

            System.out.println(id3 + "---" + name3 + "---" + balance3);*/


        } catch (ClassNotFoundException e) {
    
    
            e.printStackTrace();
        } catch (SQLException e) {
    
    
            e.printStackTrace();
        } finally {
    
    
            //7.释放资源

            if(rs != null){
    
    
                try {
    
    
                    rs.close();
                } catch (SQLException e) {
    
    
                    e.printStackTrace();
                }
            }

            if(stmt != null){
    
    
                try {
    
    
                    stmt.close();
                } catch (SQLException e) {
    
    
                    e.printStackTrace();
                }
            }

            if(conn != null){
    
    
                try {
    
    
                    conn.close();
                } catch (SQLException e) {
    
    
                    e.printStackTrace();
                }
            }
        }
    }

}

  • practise:
    • Define a method to query the data of the emp table and encapsulate it as an object, then load the collection and return.
      1. Define the Emp class
      2. define methodpublic List<Emp> findAll(){}
      3. implementation method select * from emp;

Simple package of JDBC utils

package cn.xxx.util;

import java.io.FileReader;
import java.io.IOException;
import java.net.URL;
import java.sql.*;
import java.util.Properties;

/**
 * JDBC工具类
 */
public class JDBCUtils {
    
    
    private static String url;
    private static String user;
    private static String password;
    private static String driver;
    /**
     * 文件的读取,只需要读取一次即可拿到这些值。使用静态代码块
     */
    static{
    
    
        //读取资源文件,获取值。

        try {
    
    
            //1. 创建Properties集合类。
            Properties pro = new Properties();

            //获取src路径下的文件的方式--->ClassLoader 类加载器
            ClassLoader classLoader = JDBCUtils.class.getClassLoader();
            URL res  = classLoader.getResource("jdbc.properties");
            String path = res.getPath();
           // System.out.println(path);///D:/IdeaProjects/itcast/out/production/day04_jdbc/jdbc.properties
            //2. 加载文件
           // pro.load(new FileReader("D:\\IdeaProjects\\itcast\\day04_jdbc\\src\\jdbc.properties"));
            pro.load(new FileReader(path));

            //3. 获取数据,赋值
            url = pro.getProperty("url");
            user = pro.getProperty("user");
            password = pro.getProperty("password");
            driver = pro.getProperty("driver");
            //4. 注册驱动
            Class.forName(driver);
        } catch (IOException e) {
    
    
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
    
    
            e.printStackTrace();
        }
    }


    /**
     * 获取连接
     * @return 连接对象
     */
    public static Connection getConnection() throws SQLException {
    
    

        return DriverManager.getConnection(url, user, password);
    }

    /**
     * 释放资源
     * @param stmt
     * @param conn
     */
    public static void close(Statement stmt,Connection conn){
    
    
        if( stmt != null){
    
    
            try {
    
    
                stmt.close();
            } catch (SQLException e) {
    
    
                e.printStackTrace();
            }
        }

        if( conn != null){
    
    
            try {
    
    
                conn.close();
            } catch (SQLException e) {
    
    
                e.printStackTrace();
            }
        }
    }


    /**
     * 释放资源
     * @param stmt
     * @param conn
     */
    public static void close(ResultSet rs,Statement stmt, Connection conn){
    
    
        if( rs != null){
    
    
            try {
    
    
                rs.close();
            } catch (SQLException e) {
    
    
                e.printStackTrace();
            }
        }

        if( stmt != null){
    
    
            try {
    
    
                stmt.close();
            } catch (SQLException e) {
    
    
                e.printStackTrace();
            }
        }

        if( conn != null){
    
    
            try {
    
    
                conn.close();
            } catch (SQLException e) {
    
    
                e.printStackTrace();
            }
        }
    }

}

package cn.xxx.domain;

import java.util.Date;

/**
 * 封装Emp表数据的JavaBean
 */
public class Emp {
    
    
    private int id;
    private String ename;
    private int job_id;
    private int mgr;
    private Date joindate;
    private double salary;
    private double bonus;
    private int dept_id;


    public int getId() {
    
    
        return id;
    }

    public void setId(int id) {
    
    
        this.id = id;
    }

    public String getEname() {
    
    
        return ename;
    }

    public void setEname(String ename) {
    
    
        this.ename = ename;
    }

    public int getJob_id() {
    
    
        return job_id;
    }

    public void setJob_id(int job_id) {
    
    
        this.job_id = job_id;
    }

    public int getMgr() {
    
    
        return mgr;
    }

    public void setMgr(int mgr) {
    
    
        this.mgr = mgr;
    }

    public Date getJoindate() {
    
    
        return joindate;
    }

    public void setJoindate(Date joindate) {
    
    
        this.joindate = joindate;
    }

    public double getSalary() {
    
    
        return salary;
    }

    public void setSalary(double salary) {
    
    
        this.salary = salary;
    }


    public int getDept_id() {
    
    
        return dept_id;
    }

    public void setDept_id(int dept_id) {
    
    
        this.dept_id = dept_id;
    }


    public double getBonus() {
    
    
        return bonus;
    }

    public void setBonus(double bonus) {
    
    
        this.bonus = bonus;
    }


    @Override
    public String toString() {
    
    
        return "Emp{" +
                "id=" + id +
                ", ename='" + ename + '\'' +
                ", job_id=" + job_id +
                ", mgr=" + mgr +
                ", joindate=" + joindate +
                ", salary=" + salary +
                ", bonus=" + bonus +
                ", dept_id=" + dept_id +
                '}';
    }
}

package cn.xxx.jdbc;

import cn.xxx.domain.Emp;
import cn.xxx.util.JDBCUtils;

import java.sql.*;
import java.util.ArrayList;
import java.util.List;

/**
 * * 定义一个方法,查询emp表的数据将其封装为对象,然后装载集合,返回。
 */
public class JDBCDemo8 {
    
    

    public static void main(String[] args) {
    
    
        List<Emp> list = new JDBCDemo8().findAll2();
        System.out.println(list);
        System.out.println(list.size());
    }

    /**
     * 查询所有emp对象,演示JDBC工具类
     * @return
     */
    public List<Emp> findAll2(){
    
    
        Connection conn = null;
        Statement stmt = null;
        ResultSet rs = null;
        List<Emp> list = null;
        try {
    
    
           /* //1.注册驱动
            Class.forName("com.mysql.jdbc.Driver");
            //2.获取连接
            conn = DriverManager.getConnection("jdbc:mysql:///db3", "root", "root");*/
            conn = JDBCUtils.getConnection();
            //3.定义sql
            String sql = "select * from emp";
            //4.获取执行sql的对象
            stmt = conn.createStatement();
            //5.执行sql
            rs = stmt.executeQuery(sql);
            //6.遍历结果集,封装对象,装载集合
            Emp emp = null;
            list = new ArrayList<Emp>();
            while(rs.next()){
    
    
                //获取数据
                int id = rs.getInt("id");
                String ename = rs.getString("ename");
                int job_id = rs.getInt("job_id");
                int mgr = rs.getInt("mgr");
                Date joindate = rs.getDate("joindate");
                double salary = rs.getDouble("salary");
                double bonus = rs.getDouble("bonus");
                int dept_id = rs.getInt("dept_id");
                // 创建emp对象,并赋值
                emp = new Emp();
                emp.setId(id);
                emp.setEname(ename);
                emp.setJob_id(job_id);
                emp.setMgr(mgr);
                emp.setJoindate(joindate);
                emp.setSalary(salary);
                emp.setBonus(bonus);
                emp.setDept_id(dept_id);

                //装载集合
                list.add(emp);
            }

        } catch (SQLException e) {
    
    
            e.printStackTrace();
        }finally {
    
    
            /*if(rs != null){
                try {
                    rs.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }

            if(stmt != null){
                try {
                    stmt.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }

            if(conn != null){
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }*/

            JDBCUtils.close(rs,stmt,conn);
        }
        return list;
    }

}

Simple login using JDBC utils

package cn.xxx.jdbc;

import cn.xxx.util.JDBCUtils;

import java.sql.*;
import java.util.Scanner;

/**
 * 练习:
 * 		* 需求:
 * 			1. 通过键盘录入用户名和密码
 * 			2. 判断用户是否登录成功
 */
public class JDBCDemo9 {
    
    

    public static void main(String[] args) {
    
    
        //1.键盘录入,接受用户名和密码
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入用户名:");
        String username = sc.nextLine();
        System.out.println("请输入密码:");
        String password = sc.nextLine();
        //2.调用方法
        boolean flag = new JDBCDemo9().login(username, password);
        //3.判断结果,输出不同语句
        if(flag){
    
    
            //登录成功
            System.out.println("登录成功!");
        }else{
    
    
            System.out.println("用户名或密码错误!");
        }


    }



    /**
     * 登录方法
     */
    public boolean login(String username ,String password){
    
    
        if(username == null || password == null){
    
    
            return false;
        }
        //连接数据库判断是否登录成功
        Connection conn = null;
        Statement stmt =  null;
        ResultSet rs = null;
        //1.获取连接
        try {
    
    
            conn =  JDBCUtils.getConnection();
            //2.定义sql
            String sql = "select * from user where username = '"+username+"' and password = '"+password+"' ";
            System.out.println(sql);
            //3.获取执行sql的对象
            stmt = conn.createStatement();
            //4.执行查询
            rs = stmt.executeQuery(sql);
            //5.判断
           /* if(rs.next()){//如果有下一行,则返回true
                return true;
            }else{
                return false;
            }*/
           return rs.next();//如果有下一行,则返回true

        } catch (SQLException e) {
    
    
            e.printStackTrace();
        }finally {
    
    
            JDBCUtils.close(rs,stmt,conn);
        }


        return false;
    }

}

PreparedStatement

object to execute sql

  1. SQL injection problem: When splicing sql, there are some special keywords of sql that participate in the splicing of strings. It will cause security problems
    1. Enter the user casually, enter the password: a' or 'a' = 'a
    2. The final sql is: select * from user where username = 'fhdsjkf' and password = 'a' or 'a' = 'a'

  2. Solve the problem of sql injection: use the PreparedStatement object to solve it. PreparedStatement uses precompiled SQL, that is, the parameter uses? as a placeholder

  3. step:

    1. Import the driver jar package mysql-connector-java-5.1.37-bin.jar
    2. register driver
    3. Get the database connection object Connection
    4. define sql
      • Note: The parameters of sql use? as a placeholder. Such as: select * from user where username = ? and password = ?;
    5. Get the object that executes the sql statement PreparedStatement Connection.prepareStatement(String sql)
    6. Give? assignment:
      • Method: setXxx(parameter 1, parameter 2)
        • Parameter 1: ? position numbers start at 1
        • Parameter 2: ? the value of
    7. Execute sql, accept the returned result, no need to pass sql statement
    8. process result
    9. release resources
  4. Note: PreparedStatement will be used later to complete all operations of adding, deleting, modifying and checking

    1. Can prevent SQL injection
    2. higher efficiency

Rewrite the login example above

package cn.xxx.jdbc;

import cn.xxx.util.JDBCUtils;

import java.sql.*;
import java.util.Scanner;

/**
 * 练习:
 * 		* 需求:
 * 			1. 通过键盘录入用户名和密码
 * 			2. 判断用户是否登录成功
 */
public class JDBCDemo9 {
    
    

    public static void main(String[] args) {
    
    
        //1.键盘录入,接受用户名和密码
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入用户名:");
        String username = sc.nextLine();
        System.out.println("请输入密码:");
        String password = sc.nextLine();
        //2.调用方法
        boolean flag = new JDBCDemo9().login2(username, password);
        //3.判断结果,输出不同语句
        if(flag){
    
    
            //登录成功
            System.out.println("登录成功!");
        }else{
    
    
            System.out.println("用户名或密码错误!");
        }


    }

    /**
     * 登录方法,使用PreparedStatement实现
     */
    public boolean login2(String username ,String password){
    
    
        if(username == null || password == null){
    
    
            return false;
        }
        //连接数据库判断是否登录成功
        Connection conn = null;
        PreparedStatement pstmt =  null;
        ResultSet rs = null;
        //1.获取连接
        try {
    
    
            conn =  JDBCUtils.getConnection();
            //2.定义sql
            String sql = "select * from user where username = ? and password = ?";
            //3.获取执行sql的对象
            pstmt = conn.prepareStatement(sql);
            //给?赋值
            pstmt.setString(1,username);
            pstmt.setString(2,password);
            //4.执行查询,不需要传递sql
            rs = pstmt.executeQuery();
            //5.判断
           /* if(rs.next()){//如果有下一行,则返回true
                return true;
            }else{
                return false;
            }*/
            return rs.next();//如果有下一行,则返回true

        } catch (SQLException e) {
    
    
            e.printStackTrace();
        }finally {
    
    
            JDBCUtils.close(rs,pstmt,conn);
        }


        return false;
    }


}

JDBC control transaction

Steps

1. Start the transaction

  • setAutoCommit(boolean autoCommit): Call this method to set the parameter to false, that is, start the transaction
  • Start the transaction before executing sql

2. Submit the transaction

  • commit()
  • When all sql are executed and the transaction is committed

3. Rollback transaction

  • rollback()
  • Rollback transaction in catch

example

package cn.xxx.jdbc;

import cn.xxx.util.JDBCUtils;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

/**
 * 事务操作
 */
public class JDBCDemo10 {
    
    


    public static void main(String[] args) {
    
    
        Connection conn = null;
        PreparedStatement pstmt1 = null;
        PreparedStatement pstmt2 = null;

        try {
    
    
            //1.获取连接
            conn = JDBCUtils.getConnection();
            //开启事务
            conn.setAutoCommit(false);

            //2.定义sql
            //2.1 张三 - 500
            String sql1 = "update account set balance = balance - ? where id = ?";
            //2.2 李四 + 500
            String sql2 = "update account set balance = balance + ? where id = ?";
            //3.获取执行sql对象
            pstmt1 = conn.prepareStatement(sql1);
            pstmt2 = conn.prepareStatement(sql2);
            //4. 设置参数
            pstmt1.setDouble(1,500);
            pstmt1.setInt(2,1);

            pstmt2.setDouble(1,500);
            pstmt2.setInt(2,2);
            //5.执行sql
            pstmt1.executeUpdate();
            // 手动制造异常,如果没有开启事务,那么pstmt1执行成功了,pstmt2就没有执行。开启事务后都没有执行
            int i = 3/0;

            pstmt2.executeUpdate();
            //提交事务
            conn.commit();
        } catch (Exception e) {
    
    
            //事务回滚
            try {
    
    
                if(conn != null) {
    
    
                    conn.rollback();
                }
            } catch (SQLException e1) {
    
    
                e1.printStackTrace();
            }
            e.printStackTrace();
        }finally {
    
    
            JDBCUtils.close(pstmt1,conn);
            JDBCUtils.close(pstmt2,null);
        }


    }

}

Guess you like

Origin blog.csdn.net/weixin_43972437/article/details/132251720