JavaJDBC基础使用教程

Posted 意愿三七

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JavaJDBC基础使用教程相关的知识,希望对你有一定的参考价值。

JDBC

一、JDBC简介

JDBC 通过Java代码来操作数据库

实际工作中大部分的数据库操作,都是通过代码来完成的.格子编程语言都可以操作数据库,主要是数据库提供了各种版本的API(一组函数 / 一组类),调用这些API就可以操作数据库。

但是我们要注意:数据库的种类有许多,不同的数据库,提供的API不太一样(因为不同的数据库是不同的厂商实现的)


程序员,要想通过代码来操作不同的数据库,就需要写多份代码,操作数据库1(写一份代码),操作数据库二(写一份代码),这样造成开发成本变高,学习成本变高。

那么我们想解决这个:很多编程语言的做法,就是把各种数据库的API再次封装一层,封装出一套统一的API,其中JAVA里面,这样的封装就是由Java标准库来完成的,此时这一套封装,称为JDBC

更准确的说JDBC就是Java标准库提供的API,这组API相当于把不同的数据库都统一成一种风格了,通过这一组API,就可以操作任何数据库(不需要关心数据库与数据库之间,API细节的差异了)


二、JDBC原理

这里看一个图:

了解了上面,我们开始进行JDBC开发。

JDBC API 是标准库自带的,直接使用


二、 JDBC使用

mysql的JDBC驱动,这个不是系统自带的,需要额外的进行下载安装

那么我们怎么安装呢?在哪里下载

  1. 对应的官网对应MySQL的JDBC驱动来说,一定可以在官网找到(Oracle管网)
  2. 对应开源的库,可以去github对应的项目主页,去找,
  3. 中央仓库,有一些大佬,搞的第三方中央仓库,中央仓库上收集许多第三方库,后面一些第三方也会主动把自己上传到这个库上。

但是上面的前2个方法很难找到,官网的差别很大,我们这里一般是中央仓库,后面的学习中用到的第三方库,全是中央仓库去找。

中央仓库地址


然后点进去发现有许多版本,我们选择什么版本呢?具体使用什么版本还是看你安装的mysql服务器的版本~

Mysql主流的服务器版本就是两套

  1. 8.x系列(使用8.x系列)

  2. 5.x系列 (使用5.1.x系列) 小版本区别不大,关键是大版本

小版本指的是:5.1.49 和5.1.48 这些区别不大,如果5版本使用8版本的 可能会出现连不上的问题。

下载:点击按钮下载驱动

这个驱动包,是一个jar包,就称为jar包,这是java程序打包部署的一种常见格式,这个.jar 就和压缩包类似,jar包本质就是把一些.class文件以压缩包的形式,给打包在一起了


引用jar包:开始使用 先来搞一个简单的以后教大家更加科学的方式:


开始JDBC 写代码

使用mysql workbench,也需要建立一个连接,也需要指定数据库的ip和端口

ip:127.0.0.1表示主机自身 (是区分在哪个主机上)
port:3306安装数据库服务器的时候,手动设置的一般默认就是3306(区分在主机上的什么程序上)

使用JDBC来实现数据库的增加:

我们这里有个insert方法里面就是写代码来实现功能

  1. 创建一个数据源
    DataSource 是标准库里面的,也就是自带的,它是一个interface 接口
    MysqlDataSource 是jar包的,也就是说如果jar包没有导入成功就没有办法使用 实现了DataSource interface的类

DataSource 这个概念表示“数据库在哪里”,对于Mysql来说,数据库就是一个服务器程序,因此就可以通过DataSource 来描述服务器的地址,端口,用户名,密码,要访问数据库名等等

  1. 把数据库的位置信息,设置到. DataSource 中
    1)数据库的ip端口 ,数据名通过URL表示
    使用到一个 setUTL 这个方法,这个setURL方法属于 MysqlDataSource 不是DataSource 的方法,此处需要向下转型

    这个操作涉及了向下转型,我们为什么要这样写:
    使用这种转型的写法,也很常见,带来的好处就是,代码中其他部分拿到的dataSource都是 DataSource类型,和具体的数据库种类无关.日后如果需要切换数据库,其他代码就完全不用改动了.

比如使用的是MysqlDataSource ,因为MysqlDataSource 是Mysql的如果数据库变量了那么其他需要变一点不方便
来看看set.URL里面的内容分别是什么意思

还有新增的2个 useSSL:加密



为什么要加密:

到底需要打开吗加密吗?

2)设置登录数据库的用户名
MySQL支持自己创建用户.
MySQL只要安装好之后,就会自带一个用户,就是root.表示"管理员”,拥有最高的权限,可以管理其他用户的权限.当前阶段咱们不必过多的关注这里的权限.(权限的话以后到公司里,都是有专门的人来给你分配好的)
3)设置登录数据库的密码

3.连接数据库,进行真正的网络通信

这个就是开始进行网络操作,如果数据库连接上了,会返回一个实例,如果失败会抛出一个异常

啥时候会连接失败呢?原因非常多,例如 ip ,端口,密码,这些错误会失败,用户没有权限也会失败,数据库没有正确启动也会失败
异常处理 注意是这个库里面的:import java.sql.Connection;

4.构造一个SQL语句,为插入准备!
通过其他语言来操作数据库,其实还是通过SQL来完成!
这里有一个数据库,结构是这样的:

此处不需要use数据库的操作,在URL中已经设定好数据库的名字了,此时客户端连上去之后就能直接确定数据库

执行语句写好了,我们还需要执行, 有一个专门的对象 :PreparedStatement

这里要介绍一下为什么要这个对象:我们的SQL语句不一定是直接写死的值直接给你的,可能里面的信息是要动态拼接,就是不是已经给值的,说白了重要的功能是动态拼接SQL

5.执行SQL客户端把SQL通过网络请求,发送给mysql服务器,mysqk服务器来解析这个SQL请求,执行具体操作,并返回响应结果,此处使用excuteUpdate 来完成数据库内容的变更(边更包含 insert,update,delete),返回值是整数,返回多少就是影响多少行操作 executeQuery:数据查询.针对select =>返回值是个ResultSet .

最后一步:我们要关闭资源

为什么关闭,客户端通过网络和服务器建立连接,客户端和服务器之间各自会分配一些资源,来保持这样的连接信息(记录对端的ip port)每维护一个连接,就都得分配一些硬件资源,如果一直不关闭资源越耗越多,最后没有资源,程序就无法正常运行

调用close的顺序,应该是按照申请顺序的“逆序”来进行的~
前面的代码,是先创建Connection,再创建PreparedStatement
后面的代码,就是先关闭PreparedStatement,后关闭Connection

最后我们执行,全部的代码放在下面最后看看结果:

package bookManager;


import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;

import javax.sql.DataSource;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Connection;

/**
 * Created by Lin
 * Description:
 * User: Administrator
 * Date: 2022-01-14
 * Time: 14:45
 */
//通过这个类 把数据库连接操作封装一下
public class DBUtil 
    private static String url = "xxxxx";  //这个要输入自己的
    private static String username ="xxxx";
    private static String password = "xxxx";

    //接下来创建数据源
    //其实每个项目里面有一个数据源就可以了
    //像DataSource这样的实例,不应该被创建多个
    private static DataSource dataSource = new MysqlDataSource();

    //静态代码块 执行时间是在类加载阶段
    static 
        ((MysqlDataSource)dataSource).setURL(url);
        ((MysqlDataSource)dataSource).setUser(username);
        ((MysqlDataSource)dataSource).setPassword(password);
    

    //提供一个方法,来建立连接
    public static Connection getConnection() throws SQLException 
        return dataSource.getConnection();
    
    //释放资源代码
    //这里的参数不要null就关闭
    public static void close(Connection connection, PreparedStatement statement, ResultSet resultSet)
        if(resultSet != null)
            try 
                resultSet.close();
             catch (SQLException e) 
                e.printStackTrace();
            
        
        if (statement != null)
            try 
                statement.close();
             catch (SQLException e) 
                e.printStackTrace();
            
        
        if (connection !=null)
            try 
                connection.close();
             catch (SQLException e) 
                e.printStackTrace();
            
        
    




数据库最后执行成功会新增一个数据:


如果我们想动态拼接怎么办呢??

可以尝试这样的写法:

但是通过字符串拼接,确实可以动态的构造出SQL,但是不建议这样使用,这样拼接比较麻烦,另一方面这样不安全,容易被SQL注入。

那么我们要怎么样实现,更加安全呢?


我们只需要把,SQL语句的拼接全部变成? ?,这样也可以清楚的看清楚我们有那几个值,而且也更加方便,下面是赋值


那个1,就是id替换了第一个?的地方,那个2就是name替换了第二个? 然后第一个是int类型,第二个替换成String类型的。

statement就支持一组setxxx 这样的方法,xxx值得是一个具体的类型~,根据要设置的类型不同,来决定使用不同的方法,数据库的所以的类型基本上全都支持

setxxx方法内部对于设置的值,进行了比较严格的校验,如果用户插入的内容是包含这种疑似SQL注入的时候,setxxx 就可以识别出来。

我们可以看statement里面的SQL

拼装后的样子:

最后数据库也成功了:

public static  void insert2() throws SQLException 
        //1. 创建一个数据库源
        MysqlDataSource dataSource = new MysqlDataSource();
        ((MysqlDataSource)dataSource).setURL("jdbc:mysql://127.0.0.1:3306/java101?characterEncoding=utf8&&useSSL=false");
        ((MysqlDataSource)dataSource).setUser("root");
        ((MysqlDataSource)dataSource).setPassword("200224");

        //2.连接数据库,进行真正的网络通信
        Connection connection = dataSource.getConnection();

        //3.构造一SQL语句,为插入做准备
        //此处不需要use数据库的操作,在URL中已经设定好数据库的名字了,此时客户端连上去之后就能直接确定数据库
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入学号");
        int id = scanner.nextInt();
        System.out.println("请输入姓名");
        String name = scanner.next();

        String sql = "insert into test values (?,?)";
        //执行SQL 专门的对象prepareStatement
        PreparedStatement statement = connection.prepareStatement(sql);
        statement.setInt(1,id);
        statement.setString(2,name);
        System.out.println("sql"+statement);

        //影响行数
        int ret = statement.executeUpdate();
        System.out.println("ret:"+ret);

        //执行完SQL之后,还要回收一些资源
        statement.close();
        connection.close();
    

写完了插入,我们来写一下删除呗:

 public static void delete() throws SQLException 
        //删除和插入差不多 只是把SQL从SQL变成delete
        //1.创建数据源,吧数据库的位置信息设置进去
        DataSource dataSource = new MysqlDataSource();
        ((MysqlDataSource)dataSource).setURL("jdbc:mysql://127.0.0.1:3306/java101?characterEncoding=utf8&&useSSL=false");
        ((MysqlDataSource)dataSource).setUser("root");
        ((MysqlDataSource)dataSource).setPassword("200224");
        //2.和数据库建立连接
        Connection connection= dataSource.getConnection();
        //3.构造SQL
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入要删除的id:");
        int id= scanner.nextInt();
        String sql = "delete from test where id = ?";
        PreparedStatement statement = connection.prepareStatement(sql);
        statement.setInt(1,id);
        //4.执行SQL
        int ret = statement.executeUpdate();
        System.out.println("ret="+ret);
        //5.释放资源
        statement.close();
        connection.close();
     

其实发现就是SQL有区别其他地方没有区别对吧

但是发现我们的JDBC 操作数据库是不是有点太麻烦了,的确,但是我们之后会告诉简化的方法的,毕竟代码是给我们带来方便的 。

结果:

数据库:


写一下修改:

public static  void update() throws SQLException 
        //1.创建数据源
         DataSource dataSource = new MysqlDataSource();
         ((MysqlDataSource)dataSource).setURL("jdbc:mysql://127.0.0.1:3306/java101?characterEncoding=utf8&&useSSL=false");
         ((MysqlDataSource)dataSource).setUser("root");
         ((MysqlDataSource)dataSource).setPassword("200224");
         //2.创建连接
         Connection connection = dataSource.getConnection();
         //3.构造数据库
         System.out.println("请输入要修改的id");
         Scanner scanner = new Scanner(System.in);
         int id = scanner.nextInt();
         System.out.println("请输入要修改的name");
         Scanner scanner1 = new Scanner(System.in);
         String name = scanner1.nextLine();
         String sql = "update  test set name = ? where id = ?";
         PreparedStatement statement = connection.prepareStatement(sql);
         statement.setString(1,name);
         statement.setInt(2,id);
         //4.执行SQL
         int ret = statement.executeUpdate();
         System.out.println("ret"+ret);
         //5.关闭
         statement.close();
         connection.close();

     


数据库:


查找:查询和修改插入删除,就有一些区别了!

插入删除修改,执行完的返回结果,只有一个int而已

查找操作,执行完的结果,是包含一组结果集合(一张临时表),

此处就需要写一些额外的代码,把这个临时表/结果表里的内容获取到


这个结果的集合的遍历,就非常类似于"迭代器"的遍历
resultSet.next() 获取当前行,同时切换到下一行 这个操作类似 i++

resultSet 就相当于一张表,每次next得到其中的一行,就可以进一步的根据这一行,得到里面的列

如果获取到了这一行 会返回一个true 如果遍历到了表的末尾,在尝试next 就会返回false


使用getxxx方法要和表里的类型相对

public static void search() throws SQLException 
        //1.创建数据源
         DataSource dataSource = new MysqlDataSource();
         ((MysqlDataSource)dataSource).setURL("jdbc:mysql://127.0.0.1:3306/java101?characterEncoding=utf8&&useSSL=false");
         ((MysqlDataSource)dataSource).setUser("root");
         ((MysqlDataSource)dataSource).setPassword("200224");
         //2.创建数据库
         Connection connection = dataSource.getConnection();
         //3.SQL语句
         String sql = "select * from test ";
         PreparedStatement statement = connection.prepareStatement(sql);
         //4.执行SQL语句
         ResultSet resultSet = statement.executeQuery();
         //5.遍历结果集合
         // resultSet.next() 获取当前行,同时切换到下一行 这个操作类似  i++
         //resultSet 就相当于一张表,每次next得到其中的一行,就可以进一步的根据这一行,得到里面的列
         //如果获取到了这一行 会返回一个true 如果遍历到了表的末尾,在尝试next 就会返回false
            while(resultSet.next())
                //resultSet 就表示当前的这一行
                //从这一行里面就能获取到具体的列
                int id = resultSet.getInt("id");
                String name = resultSet.getString("name");
                System.out.println("id:"+id);
                System.out.println("name:"+name);

            
            //6.释放资源
            resultSet.close();
            statement.close();
            connection.close();
     


数据库:

还有些编程语言/库里,把ResultSet也叫做光标


三、JDBC小结

1.DataSource和MysqlDataSource表示数据源(数据在哪里)

  • DataSource :通用的,能够支持各种数据库
  • MysqlDataSource:是MySQL驱动包里提供的专门针对·MySQL的类,设置用户名,密码,URL…基本信息

2 .Connection connection = dataSource.getConnection()

  • 通过DataSource来建立Connection (要先知道服务器的位置才可以连接)

3.构造SQL

PreparedStatement:

里面包含的不仅仅是SQL,要通过这个对象来把用户构造的SQL通过网络发送给服务器

Connection是自身真的服务器的位置的(从DataSource过来的)通过connection创建出的PreparedStatement,PreparedStatement也知道服务器的位置

executeQuery / executeUpdate:通过网络发送,前提知道在哪里

4.遍历结果集合

通过网络,数据集合已经拿回来了,到了本地,响应的结果已经在客户端代码的内存中,可以在本地遍历,获取内容

通过这些,大家要记住一句话,MySQL是一个“客户端 服务器” 结构的程序,服务器是Mysql的本体,负责管理数据,客户端有许多形态(cmd,workbench ,JDBC…)


四、JDBC封装

刚刚上面的代码比较冗余,许多代码重复的还写,其实我们可以把部分代码封装一下,即可轻松一点:

URL部分


接下来创建数据源

其实每个项目里面有一个数据源就可以了

像DataSource这样的实例只要有1个就可以了,不应该被创建多个


我们通过Static来修饰,此处的Static是表示的是“类成员”,“类方法”

DBUtil在程序中,只存在一份!! 这个类里面的成员,也就是只有一份了!

我们写的类,被编译成.class文件,程序运行的时候,jvm就会从指定的路径中,加载.class文件,.class文件是有固定格式的…(从jvm的实现规范上看到)

JVM就会把.class文件内容进行解析,并且加载到内存中,并且在内存构造一个“类对象”,(类对象里面就包含了这个类的关键信息,这个类叫什么名字,类里面有哪些属性,每个属性叫什么,每个属性是public还是private,还有什么方法,叫什么名字,方法的参数叫什么,返回值是啥public /private)

类就是图纸~

JVM在加载的时候,就会先看看这个类是不是已经在内存中存在了,如果存在,就不要重复加载,如果不存在才从.class加载

所以才要加static
《Python基础教程》第二章:列表和元组

java使用jdbc连接mysql数据库,表里有记录,但是查询的结果集为空,是啥原因

Linux培训基础教程

SQL2000 不指定表名,不指定表里的元素名,如何做符合条件的查找?

python基础教程

使用javajdbc连接到Oracle