【Mysql系列】05_JDBC使用

JDBC:是标准库提供的一套API。
环境:JDBC在使用的时候,需要下载并导入对应数据库的驱动包。

一、JDBC介绍

JDBC,即Java Database Connectivity,java数据库连接。是一种用于执行SQL语句的Java API,它是Java中的数据库连接规范。这个API由java.sq1.* ,javax. sq1.*包中的一些类和接口组成,它为Java开发人员操作数据库提供了一个标准的APl,可以为多种关系数据库提供统一访问。

1、JDBC原理

JDBC 为多种关系数据库提供了统一访问方式,作为特定厂商数据库访问API的一种高级抽象,它主要包含一些通用的接口类。

在这里插入图片描述
JDBC优势:

  • Java语言访问数据库操作完全面向抽象接口编程
  • 开发数据库应用不用限定在特定数据库厂商的API
  • 程序的可移植性大大增强

2、JDBC安装

JDBC驱动包下载地址《《

将这个jar包下载下来,然后直接粘贴进需要的项目当中即可。

在这里插入图片描述

在导入jar包的时候不要忘记右键:Add as library,并且要确保新建的目录和src是同一级,但不要放到src里面。

二、JDBC常见的接口和类

1、数据库连接Connection

Connection接口实现类由数据库提供,获取Connection对象通常有两种方式:

  • 一种是通过DriverManager(驱动管理类)的静态方法获取:
// 加载JDBC驱动程序
Class.forName("com.mysql.jdbc.Driver");
// 创建数据库连接
Connection connection = DriverManager.getConnection(url);
  • 一种是通过DataSource(数据源)对象获取。实际应用中会使用DataSource对象。
DataSource ds = new MysqlDataSource();
((MysqlDataSource) ds).setUrl("jdbc:mysql://localhost:3306/test");
((MysqlDataSource) ds).setUser("root");
((MysqlDataSource) ds).setPassword("root");
Connection connection = ds.getConnection();

以上两种方式的区别是:

  1. DriverManager类来获取的Connection连接,是无法重复利用的,每次使用完以后释放资源时,通过connection.close()都是关闭物理连接。
  2. DataSource提供连接池的支持。连接池在初始化时将创建一定数量的数据库连接,这些连接是可以复用的,每次使用完数据库连接,释放资源调用connection.close()都是将Conncetion连接对象回收。

在这里插入图片描述

2、Statement对象

Statement对象主要是将SQL语句发送到数据库中。JDBC API中主要提供了三种Statement对象。JDBC API中主要提供了三种Statement对象。

  • 1、Statement:用于执行不带参数的简单SQL语句。
  • 2、PreparedStatement:用于执行带或者不带参数的SQL语句,SQL语句会编译在数据库系统,执行速度快于Statement对象。
  • CallableStatement:用于执行数据库存储过程的调用。

实际开发中最常用的是PreparedStatement对象,以下对其的总结:
在这里插入图片描述

主要掌握两种执行SQL的方法:

  • executeQuery() 方法执行后返回单个结果集的,通常用于select语句
  • executeUpdate()方法返回值是一个整数,指示受影响的行数,通常用于update、insert、delete
    语句

3、ResultSet对象

ResultSet对象它被称为结果集,它代表符合SQL语句条件的所有行,并且它通过一套getXXX方法提供 了对这些行中数据的访问。
ResultSet里的数据一行一行排列,每行有多个字段,并且有一个记录指针,指针所指的数据行叫做当前数据行,我们只能来操作当前的数据行。我们如果想要取得某一条记录,就要使用ResultSet的next()方法 ,如果我们想要得到ResultSet里的所有记录,就应该使用while循环。

三、JDBC往数据库插入记录

操作:往数据库当中插入一条记录
通过JDBC操作数据库,往test数据库当中的student表里面插入一条记录:

1、创建数据源对象

1、创建数据源对象,数据源对象就描述了要访问的数据库是啥,在哪。

DataSource dataSource=new MysqlDataSource();//向上转型

在这里插入图片描述

每种数据库都会提供对应的类来实现DataSource接口。
上述代码使用到了多态,多态可以认为是封装的更进一步。

封装是把实现细节隐藏起来,让调用者不必考虑细节就能使用,从而降低调用者的使用成本和学习负担。
多态则是把实现类的类型也隐藏起来了,调用者不仅不必考虑细节,而且连它是啥类型都不管了。

在这里插入图片描述
DataSource是服务于各种数据库的,MysqlDataSource只是服务于MySQL的。
在MySQL里面,是一个客户端服务器的程序,描述服务器的位置,会使用URL这个概念来表示。
但是有的数据库,比如SQLite,就不是客户端服务器结构的,也就谈不上URL。

DataSource考虑到通用性,就不能把setURL这样的方法给搞过来。

在这里插入图片描述
关于耦合性,什么叫耦合:一个大的程序里面包含很多个部分,如果这些部分之间关联性比较强,则耦合度较高。关联性比较弱,耦合度较低。

URL:唯一资源定位符。就是网址。
当前数据库客户端(咱自己写的代码)和服务器都在咱自己的电脑上面。

在这里插入图片描述
DataSource描述了在哪里可以找到数据库的数据。URL里面就体现出数据库服务器的位置以及数据库的名字。

((MysqlDataSource)dataSource).setUser("root");//用户名
((MysqlDataSource)dataSource).setPassword("1234");//密码

用户名统一都是root(mysql自带的用户名),密码就是安装数据库的时候设置的密码。

2、让代码和数据库服务器建立连接

在这里插入图片描述

import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;

/**
 * @author Susie-Wen
 * @version 1.0
 * @description:
 * @date 2022/8/15 12:43
 */
public class JDBC {
    
    
    //通过JDBC操作数据库,往数据库里插入一条记录
    //往test数据库当中的student表里面插入一条记录:
    public static void main(String[] args) throws SQLException {
    
    
        DataSource dataSource=new MysqlDataSource();//向上转型
        ((MysqlDataSource)dataSource).setURL("jdbc:mysql://127.0.0.1:3306/test?characterEncoding=utf8&useSSL=false");
        ((MysqlDataSource)dataSource).setUser("root");//用户名
        ((MysqlDataSource)dataSource).setPassword("123456");//密码

        //2、让代码和数据库服务器建立连接
        Connection connetcion= dataSource.getConnection();
        System.out.println(connetcion);
    }
}

运行上述代码,如果没有报错,则说明连接数据库成功了。

在这里插入图片描述

如果出现如下错误,则说明用户名或者密码发生错误。
在这里插入图片描述

3、构造要执行的SQL语句(构造请求)

        //3、构造要执行的SQL语句
        String sql="insert into student values(3,'三三')";
        PreparedStatement statement=connetcion.prepareStatement(sql);

使用java/C++/Python操作数据库,本质上还是通过SQL。

在这里插入图片描述
PreparedStatement:表示一个预处理过的SQL语句对象。

4、执行SQL(发送请求&读取响应)

执行方法有两个:executeUpdate,executeQuery。

executeUpdate:对应插入删除修改语句,返回值表示。
executeQuery:对应查询语句,返回值则是返回的临时表数据。

        //4、执行SQL
        //执行方法有两个:executeUpdate,executeQuery
        int n=statement.executeUpdate();
        System.out.println("n="+n);

5、完成后,就需要关闭释放相关资源

手动释放资源:

        statement.close();
        connetcion.close();

前面的语句对象和连接对象都是需要消耗资源的,常说的资源,主要是指一些硬件资源(也有的时候指软件资源)

释放资源的顺序要和申请资源的顺序正好相反。

6、用户输入+完整代码

import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Scanner;

/**
 * @author Susie-Wen
 * @version 1.0
 * @description:
 * @date 2022/8/15 12:43
 */
public class JDBC {
    
    
    //通过JDBC操作数据库,往数据库里插入一条记录
    //往test数据库当中的student表里面插入一条记录:
    public static void main(String[] args) throws SQLException {
    
    
        DataSource dataSource=new MysqlDataSource();//向上转型
        ((MysqlDataSource)dataSource).setURL("jdbc:mysql://127.0.0.1:3306/test?characterEncoding=utf8&useSSL=false");
        ((MysqlDataSource)dataSource).setUser("root");//用户名
        ((MysqlDataSource)dataSource).setPassword("123456");//密码

        //2、让代码和数据库服务器建立连接
        Connection connetcion= dataSource.getConnection();
        //[用户输入]:通过用户输入的数据,来确定插入的值
        Scanner scanner=new Scanner(System.in);
        System.out.println("请输入要插入的学号:");
        int id=scanner.nextInt();
        System.out.println("请输入要插入的姓名:");
        String name=scanner.next();

        //3、构造要执行的SQL语句
        String sql="insert into student values(" + id +",' "+name+" ' )";
        PreparedStatement statement=connetcion.prepareStatement(sql);
        System.out.println("statement:"+statement);
        //4、执行SQL
        //执行方法有两个:executeUpdate,executeQuery
        int n=statement.executeUpdate();
        System.out.println("n="+n);
        //5、完成后,就需要关闭释放相关资源
        statement.close();
        connetcion.close();
    }
}

在这里插入图片描述
当前通过字符串拼接的方式,可以让用户输入数据进行插入,但是效果不太好。

1、代码非常乱,尤其是拼的SQL变成啥样,不太直观。

2、不安全,容易引发SQL注入漏洞。

在这里插入图片描述
因此,不应该手动拼接SQL,而应该借助PreparedStatement内部提供的SQL拼装机制。
使得代码更简单更直观,会对拼接的内容进行更严格的校验检查,避免SQL注入。

将上述代码进行更改,如下:

public class JDBC {
    
    
    //通过JDBC操作数据库,往数据库里插入一条记录
    //往test数据库当中的student表里面插入一条记录:
    public static void main(String[] args) throws SQLException {
    
    
        DataSource dataSource=new MysqlDataSource();//向上转型
        ((MysqlDataSource)dataSource).setURL("jdbc:mysql://127.0.0.1:3306/test?characterEncoding=utf8&useSSL=false");
        ((MysqlDataSource)dataSource).setUser("root");//用户名
        ((MysqlDataSource)dataSource).setPassword("123456");//密码

        //2、让代码和数据库服务器建立连接
        Connection connetcion= dataSource.getConnection();
        //[用户输入]:通过用户输入的数据,来确定插入的值
        Scanner scanner=new Scanner(System.in);
        System.out.println("请输入要插入的学号:");
        int id=scanner.nextInt();
        System.out.println("请输入要插入的姓名:");
        String name=scanner.next();

        //3、构造要执行的SQL语句[构造请求]
        //使用?作为占位符,占个位置,后面会替换成其他的值。
        String sql="insert into student values(?,?)";
        PreparedStatement statement=connetcion.prepareStatement(sql);
        statement.setInt(1,id);
        statement.setString(2,name);
        System.out.println("statement:"+statement);
        //4、执行SQL
        //执行方法有两个:executeUpdate,executeQuery
        int n=statement.executeUpdate();
        System.out.println("n="+n);
        //5、完成后,就需要关闭释放相关资源
        statement.close();
        connetcion.close();
    }
}

在这里插入图片描述
在这里插入图片描述

四、JDBC往数据库修改记录

import java.sql.Connection;
import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Scanner;

/**
 * @author Susie-Wen
 * @version 1.0
 * @description:
 * @date 2022/8/16 8:17
 */
//通过JDBC来修改数据
public class JDBCUpdate {
    
    
    public static void main(String[] args) throws SQLException {
    
    
        //1、创建数据源
        DataSource dataSource=new MysqlDataSource();
        ((MysqlDataSource)dataSource).setURL("jdbc:mysql://127.0.0.1:3306/test?characterEncoding=utf8&useSSL=false");
        ((MysqlDataSource)dataSource).setUser("root");//用户名
        ((MysqlDataSource)dataSource).setPassword("123456");//密码
        //2、建立连接
        Connection connection=dataSource.getConnection();
        //3、构造SQL
        Scanner scanner=new Scanner(System.in);
        System.out.println("请输入要修改的同学学号:");
        int id=scanner.nextInt();
        System.out.println("请输入要修改的同学姓名:");
        String name=scanner.next();
        String sql="update student set name = ? where id = ?";
        PreparedStatement statement=connection.prepareStatement(sql);
        statement.setString(1,name);
        statement.setInt(2,id);
        //4、执行SQL
        int n=statement.executeUpdate();
        System.out.println("n="+n);
        //5、关闭释放资源
        statement.close();
        connection.close();
    }
}

·

在实际开发当中,很少会直接使用JDBC,代码比较啰嗦。在实际开发当中会用到一些库/框架,来简化这里的数据库操作。(MyBatis)

各种库和框架本质上也就是针对JDBC又进行的封装。

五、JDBC往数据库删除记录

public class JDBCDelete {
    
    
    public static void main(String[] args) throws SQLException {
    
    
        //1、创建数据源
        DataSource dataSource=new MysqlDataSource();
        ((MysqlDataSource)dataSource).setURL("jdbc:mysql://127.0.0.1:3306/test?characterEncoding=utf8&useSSL=false");
        ((MysqlDataSource)dataSource).setUser("root");//用户名
        ((MysqlDataSource)dataSource).setPassword("123456");//密码
        //2、建立连接
        Connection connection=dataSource.getConnection();
        //3、构造SQL
        Scanner scanner=new Scanner(System.in);
        System.out.println("请输入要删除的同学学号:");
        int id=scanner.nextInt();
        String sql="delete from student where id = ?";
        PreparedStatement statement=connection.prepareStatement(sql);
        statement.setInt(1,id);
        //4、执行SQL
        int n=statement.executeUpdate();
        System.out.println("n="+n);
        //5、关闭释放资源
        statement.close();
        connection.close();
    }
}

在这里插入图片描述

六、JDBC往数据库查找记录

public class JDBCSelect {
    
    
    public static void main(String[] args) throws SQLException {
    
    
        //1、创建数据源
        DataSource dataSource=new MysqlDataSource();
        ((MysqlDataSource)dataSource).setURL("jdbc:mysql://127.0.0.1:3306/test?characterEncoding=utf8&useSSL=false");
        ((MysqlDataSource)dataSource).setUser("root");//用户名
        ((MysqlDataSource)dataSource).setPassword("123456");//密码
        //2、建立连接
        Connection connection=dataSource.getConnection();
        //3、构造SQL
        String sql="select * from student";
        PreparedStatement statement=connection.prepareStatement(sql);
        //4、执行SQL
        ResultSet resultSet=statement.executeQuery();
        //5、遍历结果集合
        while(resultSet.next()){
    
    
            //每次循环,就能够获取到resultSet中的一行,进一步的就可以拿到每一列
            int id=resultSet.getInt("id");
            String name=resultSet.getString("name");
            System.out.println("id="+id+",name="+name);
        }
        //6、关闭释放资源
        resultSet.close();
        statement.close();
        connection.close();
    }
}

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

七、JDBC作业

1、新增记录

新增貂蝉同学的借阅记录:诗经,从2019年9月25日17:50到2019年10月25日17:50

package com.bit.util;
import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;
import javax.sql.DataSource;
import java.sql.*;
import java.text.ParseException;
import java.text.SimpleDateFormat;
public class Util {
    
    
//使用连接池
  private static final DataSource DATA_SOURCE    = new MysqlDataSource();
  static {
    
    
    ((MysqlDataSource) DATA_SOURCE).setUrl("jdbc:mysql://localhost:3306/book");
    ((MysqlDataSource) DATA_SOURCE).setUser("root");
    ((MysqlDataSource) DATA_SOURCE).setPassword("root");
  }
  public static void main(String[] args) {
    
    
    System.out.println(getConnection());
  }
// 获取数据库连接
  public static Connection getConnection(){
    
    
    try {
    
    
      return DATA_SOURCE.getConnection();
    } catch (SQLException e) {
    
    
      throw new RuntimeException("获取数据库连接失败", e);
    }
  }
// 释放资源
  public static void close(ResultSet resultSet, Statement statement,
               Connection connection){
    
    
      try {
    
    
        if(resultSet != null) {
    
    
          resultSet.close();
        }
        if(statement != null){
    
    
          statement.close();
        }
        if(connection != null){
    
    
          connection.close();
        }
      } catch (SQLException e) {
    
    
        throw new RuntimeException("数据库操作异常", e);
      }
  }
//日期字符串转Java日期类Date和sql时间戳Timestamp
  public static Timestamp getTimestamp(String dateString){
    
    
    try {
    
    
     // 年-月-日 小时:分钟:秒
      java.util.Date date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(dateString);
      return new java.sql.Timestamp(date.getTime());
    } catch (ParseException e) {
    
    
      throw new RuntimeException("日期格式化错误:"+dateString, e);
    }
  }
}
package com.bit.book;
import com.bit.util.Util;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class AddBorrow {
    
    
  /**
   * 新增貂蝉同学的借阅记录:诗经,从2019年9月25日17:50到2019年10月25日17:50
   */
  public static void main(String[] args) {
    
    
   //1.创建数据库连接对象
    Connection connection = null;
    //2.创建操作命令对象
    PreparedStatement preparedStatement = null;
    try {
    
    
      connection = Util.getConnection();
      String sql = "insert into borrow_info(book_id, student_id," +
          " start_time, end_time) select b.id,s.id,?,?" +
          " from book b,student s where b.name=? and s.name=?";
      preparedStatement = connection.prepareStatement(sql);
      preparedStatement.setTimestamp(1, Util.getTimestamp("2019-09-25 17:50:00"));
      preparedStatement.setTimestamp(2, Util.getTimestamp("2019-10-25 17:50:00"));
      preparedStatement.setString(3, "诗经");
      preparedStatement.setString(4, "貂蝉");
      System.out.println(preparedStatement);
      //3.执行sql
      int result = preparedStatement.executeUpdate();
      System.out.println(result);
    } catch (SQLException e) {
    
    
      e.printStackTrace();
    } finally {
    
    
     //4.释放资源
      Util.close(null, preparedStatement, connection);
    }
  }
}

2、查询记录

查询计算机分类下的图书借阅信息

package com.bit.book;
import com.bit.util.Util;
import java.sql.*;
public class QueryBorrow {
    
    
  public static void main(String[] args) {
    
    
    Connection    connection    = null;
    PreparedStatement preparedStatement = null;
    ResultSet resultSet = null;
    try {
    
    
      connection = Util.getConnection();
      String sql = "SELECT bk.NAME book_name,bk.author book_author," +
          "s.NAME student_name,bi.start_time,bi.end_time" +
          " FROM borrow_info bi JOIN book bk ON bi.book_id = bk.id" +
          " JOIN category c ON bk.category_id = c.id" +
          " JOIN student s ON bi.student_id = s.id" +
          " WHERE c.NAME = ?";
      preparedStatement = connection.prepareStatement(sql);
      preparedStatement.setString(1, "计算机");
      resultSet = preparedStatement.executeQuery();
      while(resultSet.next()){
    
    
        String  bookName  = resultSet.getString("book_name");
        String  bookAuthor = resultSet.getString("book_author");
        String  studentName = resultSet.getString("student_name");
        Timestamp startTime  = resultSet.getTimestamp("start_time");
        Timestamp  endTime   = resultSet.getTimestamp("end_time");
        System.out.println(String.format("书名:%s,作者:%s,借阅者:%s," +"借阅起始日期:%s,结束日期:%s",
            bookName, bookAuthor, studentName, startTime, endTime));
      }
    } catch (SQLException e) {
    
    
      e.printStackTrace();
    } finally {
    
    
      Util.close(resultSet, preparedStatement, connection);
    }
  }
}

3、修改记录

修改图书《深入理解Java虚拟机》的价格为61.20

package com.bit.book;
import com.bit.util.Util;
import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class UpdateBook {
    
    
  public static void main(String[] args) {
    
    
    Connection    connection    = null;
    PreparedStatement preparedStatement = null;
    try {
    
    
      connection = Util.getConnection();
      String sql = "update book set price=? where name =?";
      preparedStatement = connection.prepareStatement(sql);
      preparedStatement.setBigDecimal(1, new BigDecimal("61.20"));
      preparedStatement.setString(2, "深入理解Java虚拟机");
      System.out.println(preparedStatement);
      int result = preparedStatement.executeUpdate();
      System.out.println(result);
    } catch (SQLException e) {
    
    
      e.printStackTrace();
    } finally {
    
    
      Util.close(null, preparedStatement, connection);
    }
  }
}

4、删除记录

删除id最大的一条借阅记录

package com.bit.book;
import com.bit.util.Util;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class DeleteBorrow {
    
    
  public static void main(String[] args) {
    
    
    Connection    connection    = null;
    PreparedStatement preparedStatement = null;
    try {
    
    
      connection = Util.getConnection();
      String sql = "delete from borrow_info where id =" +
          "(select r.id from (select max(id) id from borrow_info) r)";
      preparedStatement = connection.prepareStatement(sql);
      int result = preparedStatement.executeUpdate();
      System.out.println(result);
    } catch (SQLException e) {
    
    
      e.printStackTrace();
    } finally {
    
    
      Util.close(null, preparedStatement, connection);
    }
  }
}

猜你喜欢

转载自blog.csdn.net/wxfighting/article/details/126344627