文章目录

    • DriverManager
    • Connection
    • Statement
    • PreparedStatement
    • ResultSet
    • 案例
      • 案例一:JDBC控制事务
      • 案例二:SQL 注入错误演示

DriverManager

  • 概述:DriverManager 是驱动管理类

  • 作用

    • 获取数据库连接
    // 返回数据库连接的对象,url 是指定连接路径,user 是数据库用户名 password 是数据库密码static Connection getConnection(String url , String user , String password);
    • url 语法
    jdbc:mysql://IP地址(域名):端口号/数据库名称

    如果连接的是本机 MySQL 服务器,并且端口号默认则 url简写为:jdbc:mysql:///数据库名称>

  • 示例代码

    // 1、获取数据库连接对象-自行更换数据库用户名和密码Connection con = DriverManager.getConnection("jdbc:mysql:///test","root","root");

Connection

  • 概述:Connection 是数据库连接类

  • 作用

    • 获取执行 SQL 的对象
    方法作用
    Statement createStatement();返回执行 SQL 对象
    PreparedStatement prepareStatement(String sql);返回执行 SQL 对象,和上述对象有区别
    • 管理事务
    方法作用注意事项
    setAutoCommit(boolean autoCommit);开启事务方法参数设置为 false ,即开启事务,反之
    commit();提交事务事务执行中未出现错误,执行提交
    rollback();回滚事务事务执行中出现错误,执行回滚
  • 示例代码(这里只为演示,并无实际效果,具体看后续案例)

    // 1、获取数据库连接对象Connection con = DriverManager.getConnection("jdbc:mysql:///test","root","root");// 2、获取执行 SQL 对象Statement st = con.createStatement();// ? 后续会讲,看下去PreparedStatement pst = con.prepareStatement("SELECT * FROM account WHERE id = ?");// 1、开启事务con.setAutoCommit(false);// 2、提交事务con.commit();// 3、回滚事务con.rollback();

Statement

  • 概述:执行 SQL 的对象

  • 常用方法

    方法作用
    boolean execute(String sql);可以执行任意的 SQL 语句
    int executeUpdate(String sql);执行 DML、DDL语句,返回值:影响的行数,>0 则代表执行成功
    ResultSet executeQuery(String sql);执行 DQL 查询语句
  • 示例代码

    • 数据库代码
    -- 创建一个数据库CREATE DATABASE IF NOT EXISTS test CHARACTER SET utf8;-- 使用数据库USE test;-- 创建一个账户表CREATE TABLE account(id INT PRIMARY KEY AUTO_INCREMENT,NAME VARCHAR(20),balance DOUBLE);-- 向账户表中添加数据INSERT INTO account(NAME , balance) VALUES('张三',1000),('李四',1000);-- 查询账户表SELECT * FROM account;
    • Java 代码
    public class Test1 {public static void main(String[] args) throws ClassNotFoundException, SQLException {// 1、注册驱动Class.forName("com.mysql.cj.jdbc.Driver");// 2、获取数据库连接对象Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "root", "root");// 3、获取执行 SQL 对象Statement st = con.createStatement();// 4、定义 SQL 语句String sql1 = "SELECT * FROM account WHERE id = 2";String sql2 = "UPDATE account SET balance = balance - 500 WHERE id = 1";// 5、执行 SQL 语句boolean flag = st.execute(sql1);int lineNum = st.executeUpdate(sql2);ResultSet rs = st.executeQuery(sql1);// 6、输出结果System.out.println(flag + " " + lineNum);// 输出 ResultSet 结果集结果while(rs.next()){int id = rs.getInt(1);String name = rs.getString("name");double balance = rs.getDouble(3);System.out.println(id + "---" + name + "---" + balance);}// 7、释放资源st.close();con.close();}}

    运行结果:

    true 1

    2—李四—1000.0


PreparedStatement

  • 概述:执行 SQL 的对象(可以防止 SQL 注入)

    • 作用:PreparedStatement 可以防止 SQL 注入,并且效率更高
  • SQL 注入!!!

    • 问题:在拼接 SQL 时候,有一些 SQL 特殊的关键字参与字符串的拼接,会造成安全性问题?(在案例中演示什么问题)
    • 解决此问题:使用 PreparedStatement 对象来解决,预编译的 SQL 参数使用>作为占位符
  • 常用方法

    方法作用参数
    setXxx(参数1,参数2)给 ?赋值,Xxx代表数据类型参数1:?的位置编号(从1开始)
    参数2:赋给?的值
  • 示例代码(此对象如何使用)

    • 数据库代码
    -- 创建一个数据库CREATE DATABASE IF NOT EXISTS test CHARACTER SET utf8;-- 使用数据库USE test;-- 创建一个账户表CREATE TABLE account(id INT PRIMARY KEY AUTO_INCREMENT,NAME VARCHAR(20),balance DOUBLE);-- 向账户表中添加数据INSERT INTO account(NAME , balance) VALUES('张三',1000),('李四',1000);-- 查询账户表SELECT * FROM account;
    • Java 代码
    public class Test2 {public static void main(String[] args) throws ClassNotFoundException, SQLException {// 1、注册驱动Class.forName("com.mysql.cj.jdbc.Driver");// 2、获取数据库连接对象Connection con = DriverManager.getConnection("jdbc:mysql:///test", "root", "root");// 3、定义 SQL 语句,这里使用占位符 ?String sql = "UPDATE account SET balance = balance - ? WHERE id = ?";// 4、创建 执行 SQL 对象PreparedStatement pst = con.prepareStatement(sql);// 5、设置参数,给第一个?设置值为 500 给第二个?设置值为 1pst.setInt(1,500);pst.setInt(2,1);// 6、执行 SQL 语句int lineNum = pst.executeUpdate();// 7、输出结果System.out.println(lineNum);// 8、释放资源pst.close();con.close();;}}

    运行后,可看到控制台输出结果 1 ,数据库中编号 1 的balance 变成了 500


ResultSet

  • 概述:结果集对象,用来封装查询结果的

  • 常用方法

    方法作用注意事项
    boolean next();游标向下移动一行,判断当前行是否有数据有数据返回 true 无数据返回 false
    getXxx(参数);获取数据Xxx:代表数据类型
    参数是 int 类型,代表列的编号(从1开始),
    参数是 String 类型,代表列名称
  • 代码示例

    ResultSet rs = st.executeQuery(sql1);//循环判断游标是否是最后一行末尾。while(rs.next()){//获取数据int id = rs.getInt(1);String name = rs.getString("name");double balance = rs.getDouble(3);System.out.println(id + "---" + name + "---" + balance);}

案例

案例一:JDBC控制事务

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

  • 操作事务的三个步骤

    • 开始事务
    • 提交事务
    • 回滚事务
  • 代码示例(这里有很多的写法并不严谨,只是为了更好的演示效果,数据库还是上述步骤中用到过的)

    public class Test3 {public static void main(String[] args) {// 这里为了省事,简单这样写String url = "jdbc:mysql://localhost:3306/test";String user = "root";String password = "root";Connection con = null;PreparedStatement pst1 = null;PreparedStatement pst2 = null;try {// 1、注册驱动Class.forName("com.mysql.cj.jdbc.Driver");// 2、获取数据库连接con = DriverManager.getConnection(url,user,password);// 3、开启事务con.setAutoCommit(false);// 4、定义 SQL 语句,sql1 张三-500 sql2 李四+500String sql1 = "UPDATE account SET balance = balance - ? WHERE id = ?";String sql2 = "UPDATE account SET balance = balance + ? WHERE id = ?";// 5、获取执行 SQL 对象pst1 = con.prepareStatement(sql1);pst2 = con.prepareStatement(sql2);// 6、设置 占位符值pst1.setInt(1,500);pst1.setInt(2,1);pst2.setInt(1,500);pst2.setInt(2,2);// 7、执行 SQLpst1.executeUpdate();// 手动制造异常,可以运行次后,看下数据库的数字,再注释掉这行再运行,再看数据库数字int i = 3/0;pst2.executeUpdate();// 提交事务,因为遇见异常,所以这步代码并不执行con.commit();} catch (Exception e) {try{if(con != null){// 事务回滚,当 con 不为空的时候,才回滚con.rollback();}}catch (SQLException e1){e1.printStackTrace();}e.printStackTrace();} finally {try {// 释放资源pst1.close();pst2.close();con.close();} catch (SQLException e) {e.printStackTrace();}}}}

案例二:SQL 注入错误演示

  • 概述:SQL 语句拼接时,用一些特殊的关键字参与字符串拼接,会造成安全性问题

  • 代码示例

    • 数据库代码
    -- 创建数据库CREATE DATABASE IF NOT EXISTS test CHARACTER SET utf8;-- 创建 user 表CREATE TABLE USER(username VARCHAR(20),-- 用户名PASSWORD VARCHAR(20)-- 密码);-- 插入数据INSERT INTO USER VALUES('lisi',"a'or'a'='a");-- 查询数据,可发现下边 3行都会显示此条信息,这样错误太明显了,这是为什么?SELECT * FROM USER WHERE username = 'lisi' AND PASSWORD = 'a'OR'a'='a';SELECT * FROM USER WHERE username = 'fhdsjkf' AND PASSWORD = 'a' OR 'a' = 'a';SELECT * FROM USER WHERE username = 'a' AND PASSWORD = 'a' OR 'a' = 'a';

    注意:为什么上述3行都能显示呢?看下边两个框,可以知道,查询语句的条件有两个,中间又用 OR ,根据或的特性,只要满足其一即可,第二个红框,很明显一直是对的,所以就能查询出来。