JDBC

JDBC

  • 概念: Java DataBase Connectivity Java 数据库连接,Java语言操作数据库。

  • JDBC本质: 其实是官方(sun公司)定义的一套操作所有关系型数据库的规则,即接口。各个数据库厂商去实现这套接口,提供数据库驱动jar包。我们可以使用这套接口(JDBC)编程,真正执行的代码是驱动jar包中的实现类。

1.快速入门

  • 步骤:
    1. 导入驱动jar包
      1. 复制mysql-connector-java-8.0.20.jar到项目中自己创建的文件夹下,用于存放各种所需要用到的jar包的文件夹。
      2. 右键 –> Add As Library
    2. 注册驱动
    3. 获取数据库连接对象 Connection
      • 注意:新版本的jdbc需要在url后边加上?serverTimezone=GMT,否则会报错,因为数据库和系统时区差异。
    4. 定义sql
    5. 获取执行sql语句执行对象 Statement
    6. 执行sql,接收返回结果
    7. 处理结果
    8. 释放资源

2.详解各个对象

1.DriverManager:驱动管理对象

  • 功能

    1. 注册驱动:告诉程序该使用哪一个数据库驱动jar包

      • static void registerDriver​(Driver driver) 使用 DriverManager注册给定的驱动程序。

      • 写代码使用:Class.forName("com.mysql.cj.jdbc.Driver");

      • 通过查看源码发现,com.mysql.cj.jdbc.Driver类中包含一个静态代码块,其中静态代码块包含的内容中就是static void registerDriver​(Driver driver)

      • 注意:mysql5之后的驱动jar包可以省略注册驱动的步骤。

    2. 获取数据库连接

      • 方法:static Connection getConnection​(String url, String user, String password)
      • 参数:
        • url:指定连接的路径
          • 语法:jdbc:mysql://ip地址(域名):端口号/数据库名称?serverTimezone=GMT
          • 如果连接的是本机的一个mysql服务器,并且mysql服务的端口默认是3306,则这个url的ip和端口可以不写。
        • user:用户名
        • password:密码

2.Connection:数据库连接对象

  • 功能

    1. 获取执行sql的对象

      • Statement createStatement​()
      • PreparedStatement prepareStatement​(String sql)
    2. 管理事务

      • 开启事务 void setAutoCommit​(boolean autoCommit) 参数为false,则为开启事务。
      • 提交事务 void commit​()
      • 回滚事务 void rollback​()

3.Statement:执行sql的对象

  • 功能:执行sql
    1. boolean execute​(String sql) 可以执行任意sql语句。
    2. int executeUpdate​(String sql) 可以执行DML(insert,update,delete)与DDL(create,alter,drop)语句。
      • 返回值:影响的行数,可以通过这个影响的行数判断DML语句是否执行成功,返回值大于0则执行成功,反之,失败。
    3. ResultSet executeQuery​(String sql) 可以执行DQL(select)语句。

4.ResultSet:结果集对象

  • boolean next():游标向下移动一行。
  • getXxx(参数):获取数据。
    • Xxx:代表数据类型
    • 参数:
      1. int:代表列的编号,从1开始。
      2. String:代表列名称。

5.PreparedStatement:执行sql的对象,功能比Statement更强大

  1. SQL注入问题:在拼接sql时,有一些sql的特殊关键字参与字符串的拼接。会造成安全性问题。

    1. 输入用户名随便,输入密码:a’ or “a” = ‘a
    2. sql: select * from user where username=’dsadsdcz’ and password=’a’ or ‘a’=’a’;
  2. 解决SQL注入问题:使用PreparedStatement对象来解决。

  3. 预编译的SQL:参数使用?作为占位符。

  4. 步骤

    1. 导入驱动jar包
    2. 注册驱动
    3. 获取数据库连接对象 Connection
    4. 定义sql
      • 注意:sql的参数使用?作为占位符。如select * from user where username=? and password=?;
    5. 获取执行sql语句的对象PreparedStatement。Connection.PreparedStatement(String sql)
    6. 给?赋值
      • 方法:setXxx(参数1,参数2)
        • 参数1:?的位置编号,从1开始。
        • 参数2:?的值。
    7. 执行sql,接收返回结果,不需要传递sql语句
    8. 处理结果
    9. 释放资源
  • 注意:后期都会使用PreparedStatement来完成增删改查的所有操作。因为可以防止SQL注入而且效率更高。

JDBC工具类:JDBCUtils

  • 目的:简化书写
  • 分析:
    1. 注册驱动。
    2. 抽取一个方法获取连接对象。
    3. 抽取一个方法释放资源。
      • 可以不用传递参数,还能保证工具类的通用性,可以使用一个properties配置文件。

代码实现示例:

  1. properties配置文件:

    url= jdbc:mysql://localhost:3306/db2?serverTimezone=GMT
    user=root
    password=000000
    driver=com.mysql.cj.jdbc.Driver
  2. 代码

    public class JDBCUtils {
    
    private static String url = null;
    private static String user = null;
    private static String password = null;
    private static String driver = null;
    
    //静态代码块,只执行一次,用于注册驱动和变量的初始化
    static {
        try {
            Properties prop = new Properties();
            ClassLoader classLoader = JDBCUtils.class.getClassLoader();
            URL res = classLoader.getResource("jdbc.properties");
            String path = res.getPath();
            // 因为我的路径中存在中文,所以需要对其进行编码的处理
            path = URLDecoder.decode(path, StandardCharsets.UTF_8);
            System.out.println(path);
            prop.load(new FileReader(path));
            url = prop.getProperty("url");
            user = prop.getProperty("user");
            password = prop.getProperty("password");
            driver = prop.getProperty("driver");
            Class.forName(driver);
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
    
    /**
    * 获取连接的方法
    * @return Connection对象
    * @throws SQLException
    */
    public static Connection getConnection() throws SQLException {
        return DriverManager.getConnection(url, user, password);
    }
    
    /**
    * 资源释放
    * @param st
    * @param conn
    */
    public static void close(Statement st, Connection conn) {
        if (st != null) {
            try {
                st.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
        if (conn != null) {
            try {
                conn.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
    }
    
    /**
    * 资源释放
    * @param st
    * @param conn
    * @param rs
    */
    public static void close(Statement st, Connection conn, ResultSet rs) {
        if (rs != null) {
            try {
                rs.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
        if (st != null) {
            try {
                st.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
        if (conn != null) {
            try {
                conn.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
    } 
    }

JDBC控制事务

  1. 使用Connection对象来管理事务
    • 开启事务 void setAutoCommit​(boolean autoCommit) 参数为false,则为开启事务。在sql执行前开启。
    • 提交事务 void commit​()当所有sql执行完提交事务。
    • 回滚事务 void rollback​()在catch中回滚事务。
打赏
  • 版权声明: 本博客所有文章除特别声明外,均采用 Apache License 2.0 许可协议。转载请注明出处!

请我喝杯咖啡吧~

支付宝
微信