JDBC学习笔记(一) JDBC概述、获取数据库连接、使用JDBC中Statement与PreparedStatement实现增删改查

前面我们学习了MySQL的相关知识,事实上MySQL数据库管理系统就是一个服务器,例如命令行、可视化工具等都是客户端,通过提供的服务器的IP、端口号以及用户名密码等可以与服务器进行交互。
在这里插入图片描述


1.JDBC概述

在JAVA中,数据库存取技术可以分为以下几类:

  • JDBC直接访问数据库
  • JDO技术(Java Data Object):JDBC只是面向关系数据库(RDBMS),JDO更通用,提供到任何数据底层的存储功能,比如关系数据库、文件、XML以及对象数据库(ODBMS)等等,使得应用可移植性更强。
  • 第三方O/R工具,如Mybatis等。

JDBC是Java访问数据库的基石,Mybatis等只是更好的封装了JDBC.。


1.1 什么是JDBC

JDBC(Java Database Connectivity):Java连接数据库的技术。

JDBC通常指的是SUN公司为各大数据库厂商Java程序如何连接和操作DBMS软件制定的统一的标准,即公共接口。这个公共接口由各大数据库厂商提供实现类,这些实现类就构成了数据库驱动。

Java程序员编写Java代码时,只要面向接口编程就可以了,运行时将驱动实现类加到项目中即可。Java程序员只要学习SUN公司提供的JDBC的公共接口就可以了。

JDBC的作用可以下面的图进行深层次的解释。

  • 如果没有JDBC,那么Java程序访问数据库时是下图所示。不同的DBMS软件是由不同的公司开发,如果Java程序想要连接和操作DBMS不仅仅是SQL语句就够了,可能还需要其他的API(类、方式等)的支持。

在这里插入图片描述

  • JDBC为访问不同的数据库提供了一种统一的途径。JDBC的目标是使Java程序员使用JDBC可以连接任何提供了JDBC驱动程序的数据库系统,这样就使得程序员无需对特定的数据库系统的特点有一定的了解,从而极大简化了开发过程。

在这里插入图片描述

总结:JDBC是SUN公司提供一套用于数据库操作的接口API,Java程序员只需要面向这套接口编程就行。不同的数据库厂商,需要针对这套接口,提供不同实现类。不同的实现类,就是不同数据库的驱动类。


1.2 JDBC API

JDBC API是一系列的接口,它规定和规范了应用程序与数据库的连接、执行SQL语句,并等到返回结果等。声明在java.sql和javax.sql包中。

在这里插入图片描述


1.3 JDBC程序编写步骤

  • JDBC程序访问数据库的步骤见下图。
    在这里插入图片描述

2.获取数据库连接

获取数据库连接的步骤可用下面这些步骤进行实现。

(1)引入JDBC驱动程序

驱动程序由数据库提供商进行提供下载。 MySQL的驱动下载地址:http://dev.mysql.com/downloads/。

  • 如何将Java Project项目应用中添加数据库驱动jar:

  • (1)先把mysql-connector-java-5.1.36-bin.jar拷贝到项目中的libs目录中。
    在这里插入图片描述

  • (2)将jar包添加到项目的类路径下。

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述


(2)加载并注册驱动

加载并注册驱动:
加载驱动,把驱动类加载到内存中。
注册驱动,把驱动类的对象交给DriverManager管理,用于后面创建连接等使用。

1.Class.forName()

调用Class类的静态方法forName(),向其传递要加载的JDBC驱动的类名。

在这里插入图片描述


(3)获取数据库连接

可以通过DriverManager类建立到数据库的连接Connection:

DriverManager试图从已经注册的JDBC驱动程序集中选择一个适当的驱动程序。

通过DriverManager类建立到数据库的连接Connection的方法
public static Connection getConnection(String url)
public static Connection getConnection(String url,String user, String password),此方法最为常用
public static Connection getConnection(String url,Properties info)其中Properties info通常至少应该包括 “user” 和 “password” 属性

JDBC URL用来标识一个被注册的驱动程序,驱动程序管理器通过这个URL选择正确的驱动程序,从而建立到数据的连接。

jdbc:<子协议><子名称>
协议:JDBC URL 中的协议总是jdbc
子协议:子协议用来标识一个数据库驱动程序
子名称:一个标识数据库的方法。用子名称的目的是为了定位数据库提供足够的信息

例如:

在这里插入图片描述

MySQL的连接URL编写方式:
jdbc:mysql://主机名称:mysql服务端口号/数据库名称?参数=&参数=值
例如:jdbc:mysql://localhost:3306/testdb

在这里插入图片描述


(4)操作或访问数据库

数据库连接被用于向数据库服务器发送命令和SQL语句,并接受数据库返回的结果。其实一个数据库的连接就是一个Socket连接。

在java.sql包中3个接口分别定义了对数据库的调用的不同方式:

  • Statement:用于执行静态SQL语句并返回它所产生结果的对象。
  • PreparedStatement:SQL语句被预编译并存储在对象中,然后可以使用此对象多次高效执行该语句。
  • CallableStatement:用于执行SQL存储过程。

Statement

通过调用Connection对象的createStatement()方法创建该对象。

该对象用于执行静态的SQL语句,并且返回执行结果。

Statement接口中定义了下列方法用于执行SQL语句:

int excuteUpdate(String sql):执行更新操作insert、update、delete

ResultSet excuteQuery(String sql):执行查询操作select

ResultSet

通过调用Statement对象的excuteQuery()方法创建该对象。

ResultSet对象维护了一个指向当前数据行的游标,初始的时候,游标在第一行之前,可以通过ResultSet对象的next()方法移动到下一行。

ResultSet接口的常用方法
boolean next():移动到下一行
get***(String columnLabel):columnLabel使用SQL AS子句指定的列表签。如果没有指定SQL AS子句,则标签是列名称
get***(int index):索引从1开始

(5)释放资源

Connection、Statement、ResultSet都是应用程序和数据库服务器的连接资源,使用后一定要关闭,可以在finally中关闭。


3.JDBC进行增、删、改、查操作的实例代码

使用JDBC进行增加数据操作的实例代码:

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

public class JDBCTest {
    public static void main(String[] args) throws ClassNotFoundException, SQLException {
        /**
         * 1.使用JDBC向mysql数据库中添加记录
         *
         */
        //1.通过反射,加载与注册驱动类
         Class.forName("com.mysql.jdbc.Driver");
         //2.获取数据库连接
         String url="jdbc:mysql://localhost:3306/school";
         Connection connection = DriverManager.getConnection(url, "root", "root");

        //3.创建Statement对象
        Statement statement = connection.createStatement();

        //4.编写sql语句
        String sql="insert books values(7,'SpringBoot学习',230)";

        //5.执行sql语句
        int len = statement.executeUpdate(sql);//insert,update以及delete都用这个方法

        System.out.println(len>0?"添加成功":"添加失败");

        //6.关闭资源
        statement.close();
        connection.close();


    }
}

运行后的结果为:
在这里插入图片描述
在这里插入图片描述


使用JDBC进行修改数据操作的实例代码:

        /**
         * 2.使用JDBC将mysql数据库中的数据进行修改
         *
         *
         */
        //1.通过反射,加载与注册驱动类
        Class.forName("com.mysql.jdbc.Driver");
        //2.获取数据库连接
        String url="jdbc:mysql://localhost:3306/school";
        Connection connection = DriverManager.getConnection(url, "root", "root");

        //3.创建Statement对象
        Statement statement = connection.createStatement();

        //4.编写sql语句
        String sql="update books set bname='详述SpringMVC'  where bid=6 ";

        //5.执行sql语句
        int len = statement.executeUpdate(sql);//insert,update以及delete都用这个方法

        System.out.println(len>0?"修改成功":"修改失败");

        //6.关闭资源
        statement.close();
        connection.close();

运行后的结果为:
在这里插入图片描述

在这里插入图片描述


使用JDBC进行删除数据操作的实例代码:

        /***
         * 3.使用JDBC将mysql数据库中的数据进行删除操作
         */

        //1.通过反射,加载与注册驱动类
        Class.forName("com.mysql.jdbc.Driver");
        //2.获取数据库连接
        String url="jdbc:mysql://localhost:3306/school";
        Connection connection = DriverManager.getConnection(url, "root", "root");

        //3.创建Statement对象
        Statement statement = connection.createStatement();

        //4.编写sql语句
        String sql="delete  from books   where bid=2 ";

        //5.执行sql语句
        int len = statement.executeUpdate(sql);//insert,update以及delete都用这个方法

        System.out.println(len>0?"删除成功":"删除失败");

        //6.关闭资源
        statement.close();
        connection.close();;

运行后的结果为:
在这里插入图片描述
在这里插入图片描述


使用JDBC进行查询数据操作的实例代码:

        /***
         * 4.使用JDBC将mysql数据库中的数据进行查询操作
         */

        //1.通过反射,加载与注册驱动类
        Class.forName("com.mysql.jdbc.Driver");
        //2.获取数据库连接
        String url="jdbc:mysql://localhost:3306/school";
        Connection connection = DriverManager.getConnection(url, "root", "root");

        //3.创建Statement对象
        Statement statement = connection.createStatement();

        //4.编写sql语句
        String sql="select * from  books ";

        //5.执行sql语句
        ResultSet resultSet = statement.executeQuery(sql);//执行sql查询语言,使用executeQuery()

        //6.遍历resultSet
        while(resultSet.next()){
            int bid = resultSet.getInt("bid");
            String bname = resultSet.getString("bname");
            double price = resultSet.getDouble("price");

            System.out.println(bid+"=="+bname+"=="+price);
        }

        //7.关闭资源
        statement.close();
        connection.close();


    }
}

运行后的结果为;
在这里插入图片描述


4.PreparedStatement

PreparedStatement接口是Statement的子接口,它表示一条预编译过的SQL语句。

4.1 Statement的不足

(1)SQL拼接

        /**
         * 1.Statement:SQL拼接
         *
         */
        Scanner input = new Scanner(System.in);
        System.out.println("请输入书籍的名称:");
        String bname = input.next();

        System.out.println("请输入书籍的价格:");
        double price = input.nextDouble();

        //1.注册驱动
        Class.forName("com.mysql.jdbc.Driver");
        //2.连接数据库
        Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/school","root","root");
        //3.创建Statement对象
        Statement statement = connection.createStatement();
        //4.编写sql语句
        String sql="insert into books values(2,'" + bname+"'," + price + ")";
        //5.执行sql语句b
        int len = statement.executeUpdate(sql);
        System.out.println(len>0?"添加成功":"添加失败");
        //6.关闭资源
        statement.close();
        connection.close();

运行后的结果为:
在这里插入图片描述
在这里插入图片描述


(2)SQL注入

SQL注入是利用某些系统没有对用户输入的数据进行充分地检查,而在用户输入数据中注入非法的SQL语句,从而利用系统的SQL引擎完成恶意行为的做法。对于Java而言,要防范SQL注入,只要用PreparedStatement来代替Statement即可。


        /**
         * 2.Statement:SQL注入
         */

        Scanner input = new Scanner(System.in);
        System.out.println("请输入书籍的名称:");
        String bname = input.next();



        //1.注册驱动
        Class.forName("com.mysql.jdbc.Driver");
        //2.连接数据库
        Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/school","root","root");
        //3.创建Statement对象
        Statement statement = connection.createStatement();
        //4.编写sql语句
        //数据库原理  'or '1'='1
        String sql="select  bid,bname,price  from books  where bname='"+bname+"'";
        //5.执行sql语句b
        ResultSet resultSet = statement.executeQuery(sql);
        while (resultSet.next()) {
            int id = resultSet.getInt(1);
            String name = resultSet.getString(2);
            double price = resultSet.getDouble(3);

            System.out.println(id+"\t"+name+"\t"+price);
        }
        //6.关闭资源
        statement.close();
        connection.close();

运行后的结果为:
在这里插入图片描述
在这里插入图片描述


(3)处理Blob类型数据

BLOB(binary large object),二进制大对象,BLOB是数据库用来存储二进制文件的字段类型。

插入BlOB类型数必须使用PreparedStatement,因为BLOB类型的数据无法使用字符串进行拼接。

在这里插入图片描述


4.2 PreparedStatement概述

通过调用Connection对象的PreparedStatement(String sql)方法获取PreparedStatement对象。

PreparedStatement接口是Statement的子接口,它表示一条预编译过的SQL语句。

  • PreparedStatement对象所代表的SQL语句中的参数用问号(?)来表示,调用PreparedStatement对象的set()方法来设置这些参数。

  • ResultSet executeQuery()执行查询,并返回该查询生成的Result对象。

  • int executeUpdate():执行更新,包含增、删、改。

使用PreparedStatement可以解决SQL语句中的拼接

public static void add() throws ClassNotFoundException, SQLException {
         Scanner input = new Scanner(System.in);
         System.out.println("请输入书籍的编号:");
         int bid = input.nextInt();

         System.out.println("请输入书籍的名称:");
         String bname = input.next();

         System.out.println("请输入书籍的价格:");
         double price = input.nextDouble();

         //1.注册驱动
         Class.forName("com.mysql.jdbc.Driver");
         //2.连接数据库
         Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/school","root","root");

         //3.编写带?的sql语句
         String sql="insert into  books values(?,?,?)";

         //4.准备一个PreparedStatement:预编译sql
         PreparedStatement preparedStatement = connection.prepareStatement(sql);

         //5.把?用具体的值进行代替
         preparedStatement.setObject(1,bid);
         preparedStatement.setObject(2,bname);
         preparedStatement.setObject(3,price);

         //6.执行sql语句
         int len = preparedStatement.executeUpdate();
         System.out.println(len>0?"添加成功":"添加成功");

         //7.释放资源
         preparedStatement.close();
         connection.close();

     }

执行后的结果为:
在这里插入图片描述

在这里插入图片描述


使用PreparedStatement可以解决SQL注入现象

  public static void main(String[] args) throws ClassNotFoundException, SQLException {
        //从键盘输入书籍的名称,来查询书籍的信息
        Scanner input = new Scanner(System.in);

        System.out.println("请输入书籍的名称:");
        String bname = input.nextLine();//输入:计算机网络组成原理' or '1'='1
        Class.forName("com.mysql.jdbc.Driver");
        //2.获取连接
        Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/school", "root", "root");

        //3.编写sql语句
        String sql = "select * from books where bname = ?";

        //4.创建PreparedStatement
        PreparedStatement pst = connection.prepareStatement(sql);

        //插入一步,设置?号
        pst.setString(1,bname);

        //5.执行sql
        ResultSet resultSet = pst.executeQuery();

        //6.遍历resultSet
        while (resultSet.next()) {
            for (int i = 1; i <= 3; i++) {
                System.out.print(resultSet.getObject(i) + "\t");
            }
            System.out.println();
        }

        //7.关闭资源
        pst.close();
        connection.close();
        input.close();
    }

运行后的结果为:
在这里插入图片描述
在这里插入图片描述


使用PreparedStatement可以处理blob等二进制的数据类型

public static void main(String[] args) throws ClassNotFoundException, SQLException, FileNotFoundException {
        //往school库的user表中添加一条记录
        //1.注册驱动
        Class<?> aClass = Class.forName("com.mysql.jdbc.Driver");

        //2.获取连接
        Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/school", "root", "root");

        //3.编写sql语句
        String sql="insert into user values(3,?,?,?)";//避免拼接blob

        //4.创建PreparedStatement对象
        PreparedStatement pst = connection.prepareStatement(sql);

        //5.设置?号
        pst.setString(1,"chenliu");
        pst.setString(2,"12345678");
        pst.setBlob(3, new FileInputStream("E:\\xingye.jpg") );

        //6.执行sql
        int len = pst.executeUpdate();
        System.out.println(len>0?"添加成功":"添加失败");


        //7.关闭流
        pst.close();
        connection.close();

    }

运行后的结果为:
在这里插入图片描述
在这里插入图片描述


5.PreparedStatement与Statement对比

  • 代码的可读性和可维护性而言:Statement的sql拼接是个难题。
  • PreparedStatement 可以处理Blob类型的数据。
  • PreparedStatement 可以防止 SQL 注入。
  • PreparedStatement 能最大可能提高性能。

总结

在本节中获取数据库连接、使用JDBC中Statement与PreparedStatement实现增删改查,这些基本操作需要重点掌握,其次需要注意的是PreparedStatement与Statement性能之间的对比。
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值