2 Java操作数据库(上):JDBC基本使用、使用类加载器获取src下的文件路径(可以解决打包的路径问题)、JDBC处理事务、数据库连接池和Spring JDBC: JDBC Template

文章目录


前言:Java操作数据库有很多技术概要

Java操作数据库有很多技术

  • 前几年使用比较多的就是JDBC这套san公司定义的规则
  • 近几年再JDBC的规则上又衍生出来了一些流行的框架。例如Mybatis这些

这些我们都需要学习,但所有的都是基于JDBC的,所以我们先来学习单独使用JDBC是怎么做的,Mybatis这些操作数据库的框架能做的JDBC肯定也能做,只是代码复杂一点。所以我们先打好JDBC的基础再来学Mybatis这些框架就会更加简单了

零、JDBC是什么?

  • JDBC
    • 概念:Java DataBase Connectivity, Java 数据库连接, Java语言操作数据库
    • JDBC本质:其实是官方(sun公司)定义的一套操作所有关系型数据库的规则,即接口。各个数据库厂商去实现这套接口,提供数据库驱动jar包。我们可以使用这套接口(JDBC)编程,真正执行的代码是驱动iar包中的实现类
      其实就是sun公司提供了一套接口,可以通过这套接口去操作具体的数据库。各个数据库厂商就根据这套接口规则提供对应的实现类个Java程序员使用
      在这里插入图片描述

一、JDBC快速入门(快速了解)

参考视频
下面是一个简单的快速入门,后面会详细讲。

  • 步骤:
    • (1)导入驱动jar包
      mysql-connector-j-8.0.31.jar(网上一搜就能搜到,注意与MySQL版本对应起来)
    • (2)注册驱动
    • (3)获取数据库连接对象 Connection
    • (4)定义sql
    • (5)获取执行sql语句的对象 Statement
    • (6)执行sql,接收返回结果
    • (7)处理结果
    • (8)释放资源

在这里插入图片描述

package cn.hjblogs.jdbc;

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

/**
 * @author JUHE
 * @version 1.0
 * JBDC快速入门
 */
public class JbdcDemo1 {
   
    public static void main(String[] args) throws ClassNotFoundException, SQLException {
   
        // 1. 导入驱动jar包(手动导jar包即可)
        // 2. 注册驱动,不同版本的MySQL驱动注册方式不同,但基本差不多
        Class.forName("com.mysql.cj.jdbc.Driver");      // 其实就是干了一件事:使用全类名将一个类加载进内存了
        // 3. 获取数据库连接对象
        Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/db01", "root", "1234");    // 连接上了本地的db01数据库
        // 4. 定义sql
        String sql = "update tb_emp set name = '迪迦奥特曼' where id = 1";     // 将数据库中id为1的name改为迪迦奥特曼
        // 5. 获取执行sql语句的对象
        Statement stmt = conn.createStatement();
        // 6. 执行sql
        int count = stmt.executeUpdate(sql);
        // 7. 处理结果
        System.out.println(count);     // 执行成功会返回1
        // 8. 释放资源
        stmt.close();
        conn.close();
    }
}

执行成功上面代码会发现数据库内数据的确修改过来了,所以我们就实现了利用Java代码操作数据库
在这里插入图片描述

二、JDBC详解(详解JDBC中的对象类)

我们主要要学习下面5个对象:

  • DriverManager:驱动管理对象
  • Connection:数据库连接对象
  • Statement:执行sql的对象
  • Resultset:结果集对象
  • Preparedstatement:执行sql的对象

其实这五个对象都是java.sql包下的五个接口或类(如果是接口就要对应数据库的厂商提供了),这就是sun公司规定的jdbc这套规则,我们实际new出来的是具体的数据库厂商写的实现类。例如这里我们的mysql-connector-j-8.0.31.jar下的就是MySQL厂商配套写的jdbc这套规则下的接口的实现类。

1 DriverManager:驱动管理对象

在这里插入图片描述

  • DriverManager:驱动管理对象,是一个类
    • 功能:
      • 注册驱动
      • 获取数据库连接

(1)DriverManager功能1:注册驱动(告诉程序该使用哪一个数据库驱动jar)-- Class.forName(“com.mysql.cj.jdbc.Driver”)

参考视频

  • 注册驱动:告诉程序该使用哪一个数据库驱动jar
    static void registerDriver(Driver driver):注册与给定的驱动程序 DriverManager。
    写代码使用: Class.forName(“com.mysql.cj.jdbc.Driver”); // 其实就是干了一件事:使用全类名将一个类加载进内存了

  • QS1:上面两种注册驱动程序有什么区别?
    通过查看源码发现: 在com.mysql.cj.jdbc.Driver类中存在静态代码块,其实也是执行了static void registerDriver(Driver driver)
    这下就清晰了
    在这里插入图片描述

  • QS1: 注册驱动是在干什么?
    告诉程序该使用哪一个数据库驱动jar包。因为jbdc里面我们都是在面向接口编程(多态创建实现类对象),要一套代码通用所有类型的关系数据库,我们就必须告诉程序我们使用的是哪一个jar包 new出接口的实现类对象

【注】:MySQL5后面版本不需要Class.forName(“com.mysql.cj.jdbc.Driver”);单独注册驱动了,可以省略这行代码,底层封装成自动注册驱动了

(2)DriverManager功能2:获取数据库连接对象 – Connection conn = DriverManager.getConnection(‘url’, “数据库用户名”, “密码”); // 连接上了本地的db01数据库

参考视频

  • 方法: static Connection getConnection(String url,String user , String password)
    • 参数:
      • url: 指定连接的路径(每种不同数据库这里的连接路径有点不同,这里我们只介绍MySQL的)
        语法: jdbc:mysql://ip地址(域名):端口号/数据库名称
        例子: jdbc:mysql://localhost:3306/db03
        细节: 如果连接的是本机mysql服务器,并且mysql服务默认端口是3306,则url可以简写为: jdbc:mysql:///数据库名称
      • user: 数据库用户名
      • password: 密码
// 3. 获取数据库连接对象
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/db01", "root", "1234");   
// 连接上了本地的db01数据库

2 Connection:数据库连接对象(获取可以执行SQL的对象和管理事务)

【注】:查看官方文档会发现这是一个接口

(1)Connection功能1:获取可以执行SQL的对象Statement 或者 Preparedstatement

(2)Connection功能2:管理事务

  • 功能:
    • (1)获取执行sql 的对象:
      下面是获取可以执行SQL对象Statement 、Preparedstatement 的两个方法,这两个对象有什么区别后面会讲
      • Statement createStatement()
      • Preparedstatement prepareStatement(String sql)
    • (2)管理事务
      • 开启事务: void setAutoCommit(boolean autoCommit): 调用该方法设置参数为false,即开启事务
      • 提交事务: void commit()
      • 回滚事务: void rollback()
        怎么使用这些方法,后面练习中会具体演示。

3 Statement:执行sql的对象(由于存在SQL注入不安全问题所以我们后期实际开发中都是使用PreparedStatement)

【注】:查官方文档,可以发现这是一个接口

这个对象里面有几个方法是要重点掌握的

  • 执行SQL:
    • boolean execute(String sql): 可以执行任意的sql (了解即可)
      这个不常用了解即可,主要是下面这两个非常常用要掌握
    • int executeUpdate(String sql): 执行DMl (insert、update、delete)语句、DDL(create、alter、drop)语句
      返回值: 影响的行数,可以通过这个影响的行数判断DML语句是否执行成功 返回值>0的则执行成功,反之,则失败。
    • ResultSet executeQuery(String sql) : 执行DQL(select)语句

4 Resultset:结果集对象

  • Resultset: 结果集对象,封装查询结果
    我们同样学习两个方法就会了
    • next(): 游标向下移动一行
      游标,理解成指针即可,我们在SQL中select查询返回的是一个表格,这个指针一开始就是指向第一行(这个第一行指的是表头的那一行,没有数据的,表头是字段列名的哪行)
      在这里插入图片描述

    • getXxx(参数): 获取数据

      • Xxx: 代表数据类型。如: int getInt(), String getString()
      • 参数:
        (1)int: 代表列的编号,从1开始 。如: getString(1)
        (2)String: 代表列名称。如: getDouble(“字段”)

具体的使用demo见【三、JDBC具体演示(练习)】中

5 PreparedStatement:执行sql的对象,解决Statement的SQL注入不安全问题(后期开发中,都是使用这个更加安全)

public interface PreparedStatement extends Statement 可以看出 PreparedStatement接口继承了Statement接口

参考视频

  • PreparedStatement: 执行sql的对象
    • 1.SQL注入问题: 在拼接sql时,有一些sql的特殊关键字参与字符串的拼接。会造成安全性问题
      • 输入用户随便,输入密码: a’ or ‘a’ = 'a
      • sql: select * from tb_emp where username = ‘fhdsjkf’ and password = ‘a’ or ‘a’= ‘a’
      • 具体这个SQL注入注入问题是什么意思见下面的【登入练习:通过键盘录入判断员工是否登录成功(判断:username & password)】这块解释
    • 2.解决sql注入问题: 使用PreparedStatement对象来解决
    • 3.预编译的SQL: 参数使用 ? 作为占位符
    • 4.步骤:
      • 1.导入驱动jar包 mysq1-connector-java-5.1.37-bin.jar
      • 2.注册驱动
      • 3.获取数据库连接对象 Connection
      • 4.定义sql
        注意: sql 的参数使用 ? 作为占位符。如: select * from tb_emp where username =? and password =?;
      • 5.获取执行sql语句的对象 PreparedStatement Connection.prepareStatement(String sql)
      • 6.给 ? 赋值:
        方法: setXxx(参数1,参数2)
        参数1: ? 的位置编号 从1 开始
        参数2: ? 的值
      • 7.执行sql,接收返回结果,不需要传递sql语句
      • 8.处理结果
      • 9.释放资源

具体的演示还是看下面的练习【登入练习:通过键盘录入判断员工是否登录成功(判断:username & password)】

三、JDBC具体演示(练习)

1 执行DMl (insert、update、delete)语句和 执行DDL(create、alter、drop)语句

(1)tb_emp表insert一条记录(模版)

INSERT INTO tb_emp(username, password, name, gender, image, job, entrydate, dept_id, create_time, update_time)
VALUES (‘cxx’, ‘cxxwxhn’, ‘曹潇潇’, 2, ‘cxx.jpg’, 4, ‘2000-01-01’, 2, now(), now());

package cn.hjblogs.jdbc;

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

public class JbdcDemo1 {
   
    public static void main(String[] args){
   
        // 1. 导入驱动jar包(手动导jar包即可)
        // 2. 注册驱动,不同版本的MySQL驱动注册方式不同,但基本差不多
        Statement stmt = null;
        Connection conn = null;
        try {
   
            Class.forName("com.mysql.cj.jdbc.Driver");
            // 3. 定义sql
            //tb_emp表insert一条记录
            // INSERT INTO tb_emp(username, password, name, gender, image, job, entrydate, dept_id, create_time, update_time) VALUES ('cxx', 'cxxwxhn', '曹潇潇', 2, 'cxx.jpg', 4, '2000-01-01', 2, now(), now());
            String sql = "INSERT INTO tb_emp(username, password, name, gender, image, job, entrydate, dept_id, create_time, update_time)\n" +
                    "VALUES ('cxx', 'cxxwxhn', '曹潇潇', 2, 'cxx.jpg', 4, '2000-01-01', 2, now(), now())";     // 将数据库中id为1的name改为迪迦奥特曼
            // 4. 获取数据库连接对象
            conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/db01", "root", "1234");    // 连接上了本地的db01数据库
            // 5. 获取执行sql语句的对象
            stmt = conn.createStatement();
            // 6. 执行sql
            int count = stmt.executeUpdate(sql);    // 返回值是影响的行数
            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 {
   
            // 7. 释放资源
            // stmt.close();
            // conn.close();
            // 为了避免空指针异常,所以要进行非空判断
            if (stmt != null){
   
                try {
   
                    stmt.close();
                } catch (SQLException e) {
   
                    e.printStackTrace();
                }
            }
            if (conn != null){
   
                try {
   
                    conn.close();
                } catch (SQLException e) {
   
                    e.printStackTrace();
                }
            }
        }
    }
}

【注】:上面逻辑还可以进一步优化,例如数据库表中有些字段设置了唯一约束,重复添加还是会报错的,我们可以进一步优化这个问题,但是我们这里仅仅用于学习就先这样了。

(2)tb_emp表update一条记录

将SQL语句改成下面这个即可

String sql = "update tb_emp set name = '曹潇潇2' where username = 'cxx'";

(3)tb_emp表delete一条记录

将SQL语句改成下面这个即可

String sql = "delete from tb_emp where username = 'cxx'";

(4)执行DDL(create、alter、drop)语句

虽然实际中DDL语句在JDBC中基本不会用到但我们还是可以演示一下:创建一个简单的Student表吧!

将SQL语句改成下面这个即可

String sql = "create table Student(id int, name varchar(20))";

需要注意的是,DDL语句是没有影响行数的,所以模版中返回的count影响行数是0。

2 Resultset: 结果集对象,封装查询结果(练习)

  • Resultset: 结果集对象,封装查询结果
    我们同样学习两个方法就会了
    • next(): 游标向下移动一行,返回true就是有数据,返回false就是没有数据
      游标,理解成指针即可,我们在SQL中select查询返回的是一个表格,这个指针一开始就是指向第一行(这个第一行指的是表头的那一行,没有数据的,表头是字段列名的哪行)
      在这里插入图片描述

    • getXxx(参数): 获取数据

      • Xxx: 代表数据类型。如: int getInt(), String getString()
      • 参数:
        (1)int: 代表列的编号,从1开始 。如: getString(1)
        (2)String: 代表列名称。如: getDouble(“字段”)

(1)Resultset: 结果集对象基本使用

参考视频

public class JbdcDemo1 {
   
    public static void main(String[] args){
   
        // 1. 导入驱动jar包(手动导jar包即可)
        // 2. 注册驱动,不同版本的MySQL驱动注册方式不同,但基本差不多
        Statement stmt = null;
        Connection conn = null;
        ResultSet res = null;
        try {
   
            Class.forName("com.mysql.cj.jdbc.Driver");
            // 3. 定义sql
            String sql = "select * from tb_emp";
            // 4. 获取数据库连接对象
            conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/db01", "root", "1234");    // 连接上了本地的db01数据库
            // 5. 获取执行sql语句的对象
            stmt = conn.createStatement();
            // 6. 执行sql
            res = stmt.executeQuery(sql);
            // 7. 处理结果(解析res)
            res.next();
            int id = res.getInt(1);
            String name = res.getString("name");
            String username = res.getString("username");
            String password = res.getString("password");
            System.out.println("id: " + id + ", name: " + name + ", username: " + username + ", password: " + password);
            // id: 1, name: 迪迦奥特曼, username: jinyong, password: 123456

        } catch (ClassNotFoundException e) {
   
            e.printStackTrace();
        } catch (SQLException e) {
   
            e.printStackTrace();
        } finally {
   
            // 7. 释放资源
            // stmt.close();
            // conn.close();
            // 为了避免空指针异常,所以要进行非空判断
            if (res != null){
   
                try {
   
                    res.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();
                }
            }

        }
    }
}

(2)Resultset: 结果集对象,遍历结果集(模版)— 使用while循环

package cn.hjblogs.jdbc;

import java.sql.*;

/**
 * @author JUHE
 * @version 1.0
 * JBDC快速入门
 */
public class JbdcDemo1 {
   
    public static void main(String[] args){
   
        // 1. 导入驱动jar包(手动导jar包即可)
        // 2. 注册驱动,不同版本的MySQL驱动注册方式不同,但基本差不多
        Statement stmt = null;
        Connection conn = null;
        ResultSet res = null;
        try {
   
            Class.forName("com.mysql.cj.jdbc.Driver");
            // 3. 定义sql
            String sql = "select * from tb_emp";
            // 4. 获取数据库连接对象
            conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/db01", "root", "1234");    // 连接上了本地的db01数据库
            // 5. 获取执行sql语句的对象
            stmt = conn.createStatement();
            // 6. 执行sql
            res = stmt.executeQuery(sql);
            // 7. 处理结果(解析res)
            while (res.next()){
   
                int id = res.getInt("id");
                String name = res.getString("name");
                String username = res.getString("username");
                String password = res.getString("password");
                System.out.println("id: " + id + " name: " + name + " username: " + username + " password: " + password);
            }

        } catch (ClassNotFoundException e) {
   
            e.printStackTrace();
        } catch (SQLException e) {
   
            e.printStackTrace();
        } finally {
   
            // 7. 释放资源
            // stmt.close();
            // conn.close();
            // 为了避免空指针异常,所以要进行非空判断
            if (res != null){
   
                try {
   
                    res.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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值