9. MySQL -- JDBC入门

本文介绍了JDBC的基础概念,包括如何使用JDBC连接数据库、执行CRUD操作、处理事务以及数据库乱码解决方案。通过实例演示了连接MySQL、创建表、插入数据和事务处理的过程,同时提到了预防SQL注入的PreparedStatement使用方法。
摘要由CSDN通过智能技术生成

目录

JDBC入门

什么是JDBC

使用JDBC的好处:

JDBC开发使用到的包:

导入驱动Jar包

JDBC的核心API

JDBC访问数据库的步骤

DriverManager类

加载和注册驱动

DriverManager作用:

类中的方法:

使用JDBC连接数据库的四个参数:

MySQL写法

MySQL中可以简写:

乱码的处理

案例:得到MySQL的数据库连接对象

Connection接口:

Connection作用:

Connection方法:

Statement接口

Statement作用:

Statement中的方法:

释放资源

执行DDL操作

执行DML操作

执行DQL操作

 ResultSet接口:

常用数据类型转换表

需求:确保数据库中有3条以上的记录,查询所有的学员信息

关于ResultSet接口中的注意事项:

数据库工具类JdbcUtils

什么时候需要创建自己的工具类?

创建工具类

案例:用户登陆

 需求:

开发步骤:

代码:

SQL注入问题

PreparedStatement接口

继承结构与作用:

PreparedSatement的执行原理

Connection创建PreparedStatement对象

PreparedStatement接口中的方法:

PreparedSatement的好处

使用PreparedStatement的步骤:

表与类的关系

案例:使用PreparedStatement查询id为1的一条学生数据,封装成一个学生Student对象

案例:将多条记录封装成集合List,集合中每个元素是一个JavaBean实体类

PreparedStatement执行DML操作

JDBC事务的处理

准备数据

API介绍

开发步骤


JDBC入门

什么是JDBC

Java DataBase Connectivity Java数据库连接技术,使用Java来访问数据库,实现对数据库中表的增删改操作。英文缩写:CRUD Create Retreive Update Delete

JDBC规范定义接口,具体的实现由各大数据库厂商来实现

JDBC是Java访问数据库的标准规范,真正怎么操作数据库还需要具体的实现类,也就是数据库驱动。每个数据库厂商根据自家数据库的通信格式编写好自己数据库的驱动。所以我们只需要会调用JDBC接口中的方法即可,数据库驱动由数据库厂商提供。

 

使用JDBC的好处:

  1. 我们只需要会调用JDBC接口中的方法即可,使用简单
  2. 使用同一套Java代码,进行少量的修改就可以访问其他JDBC支持的数据库

 

JDBC开发使用到的包:

 

 

导入驱动Jar包

 

JDBC的核心API

 

JDBC访问数据库的步骤

  1. 由DriverManager加载和注册MySQL驱动:com.mysql.jdbc.Driver
  2. 由DriverManager创建连接对象Connection
  3. 通过Connection对象得到Statement语句对象,表示一条要执行的SQL语句
  4. 执行SQL语句,将执行的结果集ResultSet返回给客户端
  5. 释放资源,关闭连接。

注:一个服务器的连接数量是有限的,使用完以后一定要关闭连接对象释放资源。

DriverManager类

加载和注册驱动

  • 疑问:为什么这样可以注册驱动?

静态代码块是什么执行

  • 查看com.mysql.jdbc.Driver源代码
public class Driver extends NonRegisteringDriver implements java.sql.Driver {

    static {

        try {

            DriverManager.registerDriver(new Driver());   //注册驱动程序

        } catch (SQLException var1) {

            throw new RuntimeException("Can't register driver!");  //注册失败就抛出异常

        }

    }

}

 

注:JDBC3以后JDK1.5以后,注册驱动已经由JDBC自动完成了,这句话可省略。有时会保留的原因是为了兼容以前的代码。

 

com.mysql.jdbc.Driver类中的static块会创建本类对象,并注册到DriverManager中。这说明只要去加载com.mysql.jdbc.Driver类,那么就会执行这个static块,从而也就会把com.mysql.jdbc.Driver注册到DriverManager中,所以可以把注册驱动类的代码修改为加载驱动类。

       Class.forName(“com.mysql.jdbc.Driver”);

 

 

DriverManager作用:

  1. 注册和加载驱动 Class.forName("com.mysql.jdbc.Driver");
  2. 创建连接对象Connection

类中的方法:

 

使用JDBC连接数据库的四个参数:

jdbc:mysql://localhost:3306/day18?useUnicode=true&characterEncoding=UTF8

useUnicode:指定这个连接数据库的过程中,使用的字节集是Unicode字节集;

characherEncoding:指定连接数据库的过程中,使用的字节集编码为UTF-8编码。防止数据库出现乱码

请注意,mysql中指定UTF-8编码是给出的是UTF8,而不是UTF-8。要小心了!(MySQL的“utf8”实际上不是真正的UTF8

 

 

MySQL写法


注意:主机也可用IP地址替代

MySQL中可以简写:

 

 

 

 

乱码的处理

如果数据库出现乱码,可以指定参数: ?characterEncoding=utf8,表示让数据库以UTF-8编码来处理数据。

jdbc:mysql://localhost:3306/day18?characterEncoding=utf8

 

案例:得到MySQL的数据库连接对象

通过包名可以知道,这个类是由mysql厂商来实现的。

package com.itheima;



import java.sql.Connection;

import java.sql.DriverManager;

import java.sql.SQLException;

import java.util.Properties;



public class Demo02Connection {



    public static void main(String[] args) throws SQLException {

        //使用用户名、密码、URL得到连接对象

        Connection c1 = DriverManager.getConnection("jdbc:mysql://localhost:3306/day18", "root", "root");

        System.out.println("得到连接对象:" + c1);

        //使用属性对象和url得到连接对象

        //创建Properites对象

        Properties info = new Properties();

        info.setProperty("user", "root");

        info.setProperty("password", "root");

        Connection c2 = DriverManager.getConnection("jdbc:mysql:///day18", info);

        System.out.println("得到连接对象:" + c2);

    }

}

Connection接口:

Connection作用:

代表一个连接对象,创建一个语句对象Statement或PreparedStatement接口

 

Connection方法:

Statement接口

Statement作用:

代表一个要执行的SQL语句对象

 

Statement中的方法:

 

 

释放资源

  1. 需要释放的对象:结果集ResultSet,语句Statement,连接对象Connection
  2. 释放顺序:先开的后关,后开的先关。ResultSet --> Statement --> Connection
  3. 放在哪个代码块中:finally

执行DDL操作

 

  • 需求:使用JDBC在MySQL的数据库中创建一张学生表
  1. id是主键,整数类型,自增长
  2. name是varchar(20),非空
  3. 性别是boolean类型
  4. 生日是date类型
CREATE TABLE Student (

id int PRIMARY KEY auto_increment,

name VARCHAR(20) not null,

gender boolean,

birthday date

)
  • 开发步骤:
  1. 创建连接
  2. 通过连接对象得到语句对象
  3. 通过语句对象发送SQL语句给服务器,执行SQL
  4. 通过语句对象发送SQL语句给服务器
  5. 释放资源
  • 代码:
package com.itheima;



import java.sql.Connection;

import java.sql.DriverManager;

import java.sql.SQLException;

import java.sql.Statement;



public class Demo04DDL {



    public static void main(String[] args) {

        Connection conn = null;

        Statement stmt = null;

        try {

            //1)    创建连接

            conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/day18", "root", "root");

            //2)    通过连接对象得到语句对象

            stmt = conn.createStatement();

            //3)    通过语句对象发送SQL语句给服务器,执行SQL

            boolean result = stmt.execute("CREATE TABLE Student (id int PRIMARY KEY auto_increment, " + "name VARCHAR(20) not null, gender boolean, birthday date)");

            System.out.println(result);   //false 因为没有结果集

        } catch (SQLException e) {

            e.printStackTrace();

        }

        //4)   释放资源

        finally {

            if (stmt !=null) {  //关闭语句对象

                try {

                    stmt.close();

                } catch (SQLException e) {

                    e.printStackTrace();

                }

            }

            //关闭连接对象

            if (conn!=null) {

                try {

                    conn.close();

                } catch (SQLException e) {

                    e.printStackTrace();

                }

            }

        }



    }

}

 

执行DML操作

  • 需求:向学生表中添加4条记录,主键是自动增长

  • 开发步骤:
  1. 创建连接对象
  2. 创建Statement语句对象
  3. 执行SQL语句:executeUpdate(sql)
  4. 返回影响的行数
  5. 释放资源
  • 代码:
package com.itheima;



import java.sql.Connection;

import java.sql.DriverManager;

import java.sql.SQLException;

import java.sql.Statement;



/**

 * 向表中添加4条记录

 */

public class Demo05DML {



    public static void main(String[] args) throws SQLException {

        //1)   创建连接对象

        Connection conn = DriverManager.getConnection("jdbc:mysql:///day18","root","root");

        //2)   创建Statement语句对象

        Statement stmt = conn.createStatement();

        //3)   执行SQL语句:

        //4)   返回影响的行数

        int rows = stmt.executeUpdate("INSERT INTO student VALUES (null,'孙悟空',1,'1993-11-11'),(null,'孙悟天',1,'1993-11-11'),(null,'孙悟饭',1,'1993-11-11'),(null,'琪琪',0,'1993-11-11');");

        //5)   释放资源

        stmt.close();

        conn.close();

        System.out.println("添加了" + rows + "行记录");

    }

}

 

执行DQL操作

 ResultSet接口:

  • 作用:代表一个从服务器上返回结果集,封装好所有数据。我们就是从结果集中取出数据。

  • 接口中的方法: 

 

 

常用数据类型转换表

注:java.sql.Date、java.sql.Time、java.sql.Timestamp(时间戳),三个共同父类是:java.util.Date

需求:确保数据库中有3条以上的记录,查询所有的学员信息

  • 查询结果:

  • 开发步骤:
  1. 得到连接对象
  2. 得到语句对象
  3. 执行SQL语句后得到结果集ResultSet对象
  4. 循环遍历取出每一条记录
  5. 输出的控制台上
  6. 释放资源
  • 代码
package com.itheima;



import java.sql.*;



public class Demo06DQL {

    public static void main(String[] args) throws SQLException {

        //1)   得到连接对象

        Connection connn = DriverManager.getConnection("jdbc:mysql://localhost:3306/day18","root","root");

        //2)   得到语句对象

        Statement stmt = connn.createStatement();

        //3)   执行SQL语句后得到结果集ResultSet对象

        ResultSet rs = stmt.executeQuery("SELECT * FROM student");

        //4)   循环遍历取出每一条记录

        while(rs.next()) {

            //int id = rs.getInt("id");    //通过列名

            //int id = rs.getInt(1);   //通过列号

            String id = rs.getString("id");  //使用不同的类型

            String name = rs.getString("name");

            //int name = rs.getInt("name");    // java.sql.SQLException: Invalid value for getInt() - '孙悟空'

            boolean gender = rs.getBoolean("gender");

            Date birthday = rs.getDate("birthday");

            //5)    输出的控制台上

            System.out.println("编号:" + id + ",姓名:" + name + ", 性别:" + (gender?"男":"女") + ", 生日:" + birthday);

        }

        //6)   释放资源

        rs.close();

        stmt.close();

        connn.close();

    }

}

 

关于ResultSet接口中的注意事项:

  1. 如果光标在第一行之前,使用rs.getXX()获取列值,报错:Before start of result set
  2. 如果光标在最后一行之后,使用rs.getXX()获取列值,报错:After end of result set
  3. 同一列可以通过getXxx()方法得到不同的数据类型

数据库工具类JdbcUtils

什么时候需要创建自己的工具类?

如果某个方法中的代码可以在不同的地方重复使用,而且代码没有变化,我们就可以考虑将它创建成一个工具类的方法,可以重用。

 

创建工具类

  • 需求:上面的代码中出现了很多重复的代码,可以把这些公共代码抽取出来。
  • 创建类JdbcUtils包含3个方法:
  1. 可以把几个字符串定义成常量:用户名,密码,URL,驱动类
  2. 注册驱动,为了兼容以前的程序
  3. 得到数据库的连接:getConnection()
  4. 关闭所有打开的资源:
    close(Connection conn, Statement stmt)
    close(Connection conn, Statement stmt, ResultSet rs)
  • 代码
package com.itheima.utils;



import java.sql.*;



/**

 * 数据库的工具类

 */

public class JdbcUtils {



    // 几个字符串定义成常量:用户名,密码,URL,驱动类

    private static final String USER = "root";

    private static final String PASSWORD = "root";

    private static final String URL = "jdbc:mysql://localhost:3306/day18";

    private static final String DRIVER = "com.mysql.jdbc.Driver";



    //注册驱动,为了兼容以前的程序

    static {

            try {

                Class.forName(DRIVER);

            } catch (ClassNotFoundException e) {

                e.printStackTrace();

            }

    }



    /**

     * 得到数据库的连接

     */

    public static Connection getConnection()  {

        try {

            return DriverManager.getConnection(URL,USER,PASSWORD);

        } catch (SQLException e) {

            throw new RuntimeException(e);

        }

    }





    /**

     * 关闭所有打开的资源

     */

    public static void  close(Connection conn, Statement stmt) {

        if (stmt!=null) {

            try {

                stmt.close();

            } catch (SQLException e) {

                e.printStackTrace();

            }

        }

        if (conn!=null) {

            try {

                conn.close();

            } catch (SQLException e) {

                e.printStackTrace();

            }

        }

    }



    public static void close(Connection conn, Statement stmt, ResultSet rs) {

        if (rs!=null) {

            try {

                rs.close();

            } catch (SQLException e) {

                e.printStackTrace();

            }

        }

        close(conn, stmt);

    }





}

 

案例:用户登陆

 需求:

  • 有一张用户表,添加几条用户记录
create table `user`(

    id int primary key auto_increment,

    `name` varchar(20),

    `password` varchar(20)

)



insert into user values(null, 'Jack','123'),(null,'Rose','456');

select * from user;



-- 什么时候登录成功,通过用户名和密码查询的结果集中有记录表示登录成功

select * from user where name='Jack' and password='123';



-- 什么时候登录失败

select * from user where name='Jack' and password='111';



select * from user where name='NewBoy' and password='222';
  • 使用Statement字符串拼接的方式实现用户的登录, 用户在控制台上输入用户名和密码。
"select * from user where name='" + name +  "' and password='" + password + "'"

 

 

开发步骤:

  1. 得到用户从控制台上输入的用户名和密码
  2. 调用下面写的登录方法来实现登录
  3. 写一个登录的方法
  1. 通过工具类得到连接
  2. 创建语句对象,使用拼接字符串的方式生成SQL语句
  3. 查询数据库,如果有记录则表示登录成功,否则登录失败
  4. 释放资源

代码:

public class Demo07Login {



    public static void main(String[] args) {

    // 1)  得到用户从控制台上输入的用户名和密码

        Scanner scanner = new Scanner(System.in);

        System.out.println("请输入用户名:");

        String name = scanner.nextLine();

        System.out.println("请输入密码:");

        String password = scanner.nextLine();

        // 2)  调用下面写的登录方法来实现登录

        login(name, password);

    }



    //登录的方法

    private static void login(String name, String password) {

        //a)   通过工具类得到连接

        Connection conn = null;

        Statement stmt = null;

        ResultSet rs = null;

        try {

            conn = JdbcUtils.getConnection();

            //b)    创建语句对象,使用拼接字符串的方式生成SQL语句

            stmt = conn.createStatement();

            String sql = "select * from user where name='" + name + "' and password='" + password + "'";

            System.out.println(sql);

            rs = stmt.executeQuery(sql);

            //c)    查询数据库,如果有记录则表示登录成功,否则登录失败

            if (rs.next()) {

                //登录成功

                System.out.println("登录成功,欢迎您:" + name);

            } else {

                System.out.println("登录失败,请重试");

            }

        } catch (SQLException e) {

            e.printStackTrace();

        } finally {

            //d)    释放资源

            JdbcUtils.close(conn, stmt, rs);

        }

    }

}

 

 

SQL注入问题

  • 当我们输入以下密码,我们发现我们账号和密码都不对竟然登录成功了

  • 问题分析:
select * from user where name='NewBoy' and password='a' or '1'='1'

select * from user where false and false or true;

select * from user where true;  //查询所有的记录

我们让用户输入的密码和SQL语句进行字符串拼接。用户输入的内容作为了SQL语句语法的一部分,改变了原有SQL真正的意义,以上问题称为SQL注入。要解决SQL注入就不能让用户输入的密码和我们的SQL语句进行简单的字符串拼接。

PreparedStatement接口

继承结构与作用:

 

PreparedSatement的执行原理

 

Connection创建PreparedStatement对象

PreparedStatement接口中的方法:

 

 

PreparedSatement的好处

  1. prepareStatement()会先将SQL语句发送给数据库预编译。PreparedStatement会引用着预编译后的结果。可以多次传入不同的参数给PreparedStatement对象并执行。减少SQL编译次数,提高效率
  2. 安全性更高,没有SQL注入的隐患。
  3. 提高了程序的可读性
package com.itheima;



import com.itheima.utils.JdbcUtils;



import java.sql.*;

import java.util.Scanner;



public class Demo07Login {



    public static void main(String[] args) {

// 1)  得到用户从控制台上输入的用户名和密码

        Scanner scanner = new Scanner(System.in);

        System.out.println("请输入用户名:");

        String name = scanner.nextLine();

        System.out.println("请输入密码:");

        String password = scanner.nextLine();

        // 2)  调用下面写的登录方法来实现登录

        login(name, password);

    }



    //使用子接口:PreparedStatement

    private static void login(String name, String password) {

        //1. 得到连接对象

        Connection conn = null;

        PreparedStatement ps = null;

        ResultSet rs = null;

        try {

            conn = JdbcUtils.getConnection();

            //2. 创建语句对象,使用占位符

            ps = conn.prepareStatement("select * from user where name=? and password=?");

            //3. 设置占位符的真实值

            ps.setString(1, name);

            ps.setString(2, password);

            //4. 查询

            rs = ps.executeQuery();

            //5. 判断是否登录成功

            if (rs.next()) {

                System.out.println("登录成功," + name);

            } else {

                System.out.println("登录失败");

            }

        } catch (Exception e) {

            e.printStackTrace();

        } finally {

            //6. 关闭连接

            JdbcUtils.close(conn, ps, rs);

        }



    }



    /*

    //Statement登录的方法

    private static void login(String name, String password) {

        //a)   通过工具类得到连接

        Connection conn = null;

        Statement stmt = null;

        ResultSet rs = null;

        try {

            conn = JdbcUtils.getConnection();

            //b)    创建语句对象,使用拼接字符串的方式生成SQL语句

            stmt = conn.createStatement();

            String sql = "select * from user where name='" + name + "' and password='" + password + "'";

            System.out.println(sql);

            rs = stmt.executeQuery(sql);

            //c)    查询数据库,如果有记录则表示登录成功,否则登录失败

            if (rs.next()) {

                //登录成功

                System.out.println("登录成功,欢迎您:" + name);

            } else {

                System.out.println("登录失败,请重试");

            }

        } catch (SQLException e) {

            e.printStackTrace();

        } finally {

            //d)    释放资源

            JdbcUtils.close(conn, stmt, rs);

        }

    }

    */



}

 

使用PreparedStatement的步骤:

  1. 编写SQL语句,未知内容使用占位符
  2. 获得PreparedStatement对象
  3. 设置实际参数
  4. 执行SQL语句
  5. 关闭资源

 

  • 使用PreparedStatement改写上面的登录程序,看有没有SQL注入的情况
public class Demo07Login {



    public static void main(String[] args) {

// 1)  得到用户从控制台上输入的用户名和密码

        Scanner scanner = new Scanner(System.in);

        System.out.println("请输入用户名:");

        String name = scanner.nextLine();

        System.out.println("请输入密码:");

        String password = scanner.nextLine();

        // 2)  调用下面写的登录方法来实现登录

        login(name, password);

    }



    //使用子接口:PreparedStatement

    private static void login(String name, String password) {

        //1. 得到连接对象

        Connection conn = null;

        PreparedStatement ps = null;

        ResultSet rs = null;

        try {

            conn = JdbcUtils.getConnection();

            //2. 创建语句对象,使用占位符

            ps = conn.prepareStatement("select * from user where name=? and password=?");

            //3. 设置占位符的真实值

            ps.setString(1, name);

            ps.setString(2, password);

            //4. 查询

            rs = ps.executeQuery();

            //5. 判断是否登录成功

            if (rs.next()) {

                System.out.println("登录成功," + name);

            } else {

                System.out.println("登录失败");

            }

        } catch (Exception e) {

            e.printStackTrace();

        } finally {

            //6. 关闭连接

            JdbcUtils.close(conn, ps, rs);

        }



}

}

表与类的关系

 

 

 

案例:使用PreparedStatement查询id为1的一条学生数据,封装成一个学生Student对象

  • 开发步骤:
  1. 创建一个学生对象
  2. 得到连接对象
  3. 得到语句对象,SQL设置占位符
  4. 传递参数,替换占位符
  5. 将结果封装成一个学生对象
  6. 释放资源
  7. 使用数据,输出到控制台
  • 代码:

   

 //每个方法都可以运行, 必须是public void 方法不能有参数

    @Test

    public void testFindOne() throws SQLException {

        //1)   创建一个学生对象

        Student student = new Student();

        //2)   得到连接对象

        Connection conn = JdbcUtils.getConnection();

        //3)   得到语句对象,SQL设置占位符

        PreparedStatement ps = conn.prepareStatement("select * from student where id=?");

        //4)   传递参数,替换占位符

        ps.setInt(1, 1);

        ResultSet rs = ps.executeQuery();

        //5)   将结果封装成一个学生对象

        if (rs.next()) {

            student.setId(rs.getInt("id"));

            student.setName(rs.getString("name"));

            student.setGender(rs.getBoolean("gender"));

            student.setBirthday(rs.getDate("birthday"));

        }

        //6)   释放资源

        JdbcUtils.close(conn,ps,rs);

        //7)   使用数据,输出到控制台

        System.out.println(student);

    }

 

 

案例:将多条记录封装成集合List<Student>,集合中每个元素是一个JavaBean实体类

  • 需求: 查询所有的学生类,封装成List<Student>返回
  • 执行效果:

  • 开发步骤:
  1. 创建一个集合用于封装所有的记录
  2. 得到连接对象
  3. 得到语句对象,SQL语句没有占位符
  4. 每次循环封装一个学生对象
  5. 把数据放到集合中
  6. 关闭连接
  7. 使用数据,循环输出学生对象
  • 代码:

   

@Test

    public void testFindAll() throws SQLException {

        //1)   创建一个集合用于封装所有的记录

        List<Student> students = new ArrayList<>();

        //2)   得到连接对象

        Connection conn = JdbcUtils.getConnection();

        //3)   得到语句对象,SQL语句没有占位符

        PreparedStatement ps = conn.prepareStatement("select * from student");

        ResultSet rs = ps.executeQuery();

        //4)   每次循环封装一个学生对象

        while (rs.next()) {

        //5)   把数据放到集合中

            Student student = new Student();

            student.setId(rs.getInt("id"));

            student.setName(rs.getString("name"));

            student.setGender(rs.getBoolean("gender"));

            student.setBirthday(rs.getDate("birthday"));

            students.add(student);

        }

        //6)   关闭连接

        JdbcUtils.close(conn,ps,rs);

        //7)   使用数据,循环输出学生对象

        students.forEach(System.out::println);

    }

 

PreparedStatement执行DML操作

  • 需求:
  1. 向学生表中添加1条记录代码
  2. 将id为2的用户,姓名更新为"猪八戒",性别换成男
  3. 将id为4的学员删除
  • 代码:

   

 //    1)   向学生表中添加1条记录代码

    @Test

    public void testAdd() throws SQLException {

        //1.创建连接

        Connection conn = JdbcUtils.getConnection();

        //2.创建语句对象

        PreparedStatement ps = conn.prepareStatement("INSERT  into student VALUES (null,?,?,?)");

        //3. 替换占位符

        ps.setString(1, "短笛");

        ps.setBoolean(2, true);

        ps.setDate(3, Date.valueOf("1998-02-20"));  //将字符串转成日期,格式必须是:yyyy-MM-dd

        //4. 执行更新操作

        int row = ps.executeUpdate();

        //5.关闭连接

        JdbcUtils.close(conn, ps);

        System.out.println("影响的行数:" + row);

    }



    //    2)   将id为2的用户,姓名更新为"猪八戒",性别换成男

    @Test

    public void testUpdate() throws SQLException {

        //1.创建连接

        Connection conn = JdbcUtils.getConnection();

        //2.创建语句对象

        PreparedStatement ps = conn.prepareStatement("update student set name=?,gender=? where id=?");

        //3. 替换占位符

        ps.setString(1, "猪八戒");

        ps.setBoolean(2, true);

        ps.setInt(3, 2);

        //4. 执行更新操作

        int row = ps.executeUpdate();

        //5.关闭连接

        JdbcUtils.close(conn, ps);

        System.out.println("影响的行数:" + row);

    }



    //    3)   将id为4的学员删除

    @Test

    public void testDelete() throws SQLException {

        //1.创建连接

        Connection conn = JdbcUtils.getConnection();

        //2.创建语句对象

        PreparedStatement ps = conn.prepareStatement("delete from student where id=?");

        //3. 替换占位符

        ps.setInt(1, 4);

        //4. 执行更新操作

        int row = ps.executeUpdate();

        //5.关闭连接

        JdbcUtils.close(conn, ps);

        System.out.println("影响的行数:" + row);

    }

JDBC事务的处理

之前我们是使用MySQL的命令来操作事务。接下来我们使用JDBC来操作银行转账的事务。

 

准备数据

CREATE TABLE account (
    id INT PRIMARY KEY AUTO_INCREMENT,
    NAME VARCHAR(10),
    balance DOUBLE
);
-- 添加数据
INSERT INTO account (NAME, balance) VALUES ('Jack', 1000), ('Rose', 1000);

 

API介绍

 

开发步骤

  • 先试一下没有事务的转账情况
  • 使用事务的情况
  1. 获取连接
  2. 开启事务
  3. 获取到PreparedStatement
  4. 使用PreparedStatement执行两次更新操作
  5. 正常情况下提交事务
  6. 出现异常回滚事务
  7. 最后关闭资源
  • 案例代码
package com.itheima;



import com.itheima.utils.JdbcUtils;



import java.sql.Connection;

import java.sql.PreparedStatement;

import java.sql.SQLException;



public class Demo09Transaction {



    public static void main(String[] args) {

        Connection conn = null;

        PreparedStatement ps = null;

        try {

//1)   获取连接

            conn = JdbcUtils.getConnection();

            //开启事务

            conn.setAutoCommit(false);

//3)   获取到PreparedStatement

            ps = conn.prepareStatement("update account set balance = balance - 500 where name='jack'");

            ps.executeUpdate();

            System.out.println(100 / 0);

            //执行第2次

            ps = conn.prepareStatement("update account set balance = balance + 500 where name='rose'");

            ps.executeUpdate();

            //提交事务

            conn.commit();

            System.out.println("转账成功");

        } catch (Exception e) {

            System.out.println("转账失败");

            try {

                conn.rollback();

            } catch (SQLException e1) {

                e1.printStackTrace();

            }

        } finally {

//7)   最后关闭资源

            JdbcUtils.close(conn, ps);

        }

    }

}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

靈熙雲

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值