JDBC核心技术

本文详细介绍了Java中的JDBC技术,包括其基本概念、JDBC与JDO/Hibernate/MyBatis的关系,以及如何通过JDBC进行数据库连接、SQL操作、PreparedStatement的使用以避免SQL注入,以及ResultSet的处理。
摘要由CSDN通过智能技术生成

JDBC


概述

一,Java中的数据存储技术

  1. JDBC直接访问数据库
  2. JDO (Java Data Object)技术
  3. 第三方框架,如Hibernate,Mybatis等

JDBC是java访问数据库的基石,JDO、Hibernate、MyBatis只是更好的封装了JDBC

二,JDBC

  1. Java Database Connectivity(JDBC):是一个独立于特定数据库管理系统,通用的SQL数据库存取和操作的公共接口(一组API),定义了用来访问数据库的标准Java类库,可以以一种标准的方法、方便地访问数据库资源。

    • JDBC为访问不同的数据库提供了一种统一的途径
    • 使Java程序员使用JDBC可以连接任何提供了JDBC驱动程序的数据库系统
  2. 体系结构:JDBC接口(API)包括两个层次

    • 面向应用的API:Java API,抽象接口,供应用程序开发人员使用(连接数据库,执行SQL语句,获得结果)
    • 面向数据库的API:Java Driver API,供开发商开发数据库驱动程序用。

**面向接口编程:**JDBC是sun公司提供的一套用于数据库操作的接口,Java程序员只需要面向这套接口编程即可。不同的数据库厂商,需要针对这套接口,提供不同实现,即不同的数据库驱动。

三,JDBC程序的编写步骤

image-20220618100847182

ODBC(Open Database Connectivity,开放式数据库连接),是微软在Windows平台下推出的。使用者在程序中只需要调用ODBC API,由ODBC驱动程序将调用转换成为对特定的数据库的调用请求。

获取数据库连接

一,Driver(驱动)接口 - 实现数据库连接的起始点

  1. **概述:java.sql.Driver**接口是所有JDBC驱动程序需要实现的接口。这个接口是提供给数据库厂商使用的,不同数据库厂商提供不同的实现。

    在程序中不需要直接去访问实现了Driver接口的类,而是由驱动程序管理器类(java.sql.DriverManager)去调用这些Driver实现。

  2. Oracle的驱动oracle.jdbc.driver.OracleDriver

  3. MySql的驱动

    • Java 5 及以下:com.mysql.jdbc.Driver
    • Java 6 及以上:com.mysql.cj.jdbc.Driver

    如果使用的jar包是Java 6 及以上的,却使用了com.mysql.jdbc.Driver就会报如下异常:

    Loading class 'com.mysql.jdbc.Driver'. This is deprecated. The new driver class is 'com.mysql.cj.jdbc.Driver

二,加载与注册驱动

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

    Class.forName("com.mysql.cj.jdbc.Driver");
    

    Applications no longer need to explicitly load JDBC drivers using Class.forName(). Existing programs which currently load JDBC drivers using Class.forName() will continue to work without modification.

  2. **注册驱动:**DriverManager类是驱动程序管理器类,负责管理驱动程序

    DriverManager.registerDriver(com.mysql.jdbc.Driver);
    

    通常不用显式调用registerDriver()方法来注册驱动程序类的实例,因为Driver接口的驱动程序类都包含了静态代码块,在这个静态代码块中,会调用DriverManager.registerDriver()方法来注册自身的一个实例

三,JDBC URL

  1. URL:JDBC URL用于标识一个被注册的驱动程序,驱动程序管理器通过这个URL选择正确的驱动程序,从而建立到数据库的连接
image-20220618112342152
  • 协议:JDBC URL中的协议总是jdbc
  • 子协议:子协议用于标识一个数据库驱动程序
  • 子名称:一种标识数据库的方法,包含主机名(对应服务端的ip地址),端口号,数据库名
  1. MySQL的连接URL编写jdbc:mysql://主机名称:端口号/数据库名称?参数=值&参数=值

    jdbc:mysql://localhost:3306/test
    

    如果JDBC程序与服务器端的字符集不一致,会导致乱码,那么可以通过参数指定服务器端的字符集

    jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8
    

四,获取连接

  1. 方式一

    private static void testConnection() throws ClassNotFoundException, SQLException {
        	// 注册驱动
            Class.forName("com.mysql.cj.jdbc.Driver");
        	// 获取数据库连接对象
            Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/test","root","123456");
            // 获取执行sql的对象Statement
            Statement stat = con.createStatement();
    }
    
  2. 方式二:将数据库连接使用的基本信息声明在配置文件

    private static void testConnection() throws ClassNotFoundException, SQLException {
        	// 加载配置文件
            InputStream is = ConnectionTest.class.getClassLoader().getResourceAsStream("jdbc.properties");
            Properties pros = new Properties();
            pros.load(is);
        	// 读取配置信息
            String user = pros.getProperty("user");
            String password = pros.getProperty("password");
            String url = pros.getProperty("url");
            String driverClass = pros.getProperty("driverClass");
        	// 注册驱动
            Class.forName("com.mysql.cj.jdbc.Driver");
        	// 获取数据库连接对象
            Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/test","root","123456");
            // 获取执行sql的对象Statement
            Statement stat = con.createStatement();
    }
    

    Java.util.Properties(Properties):该类主要用于读取Java的配置文件,其配置文件常为.properties文件,是以键值对的形式进行参数配置的

使用PreparedStatement实现CRUD操作

一,操作和访问数据库

  1. **DRUD:**创建(creat)、读取(read)、修改(update)、删除(delete)

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

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

    在实际开发中由于Statement接口存在的弊端,通常使用Statement的子接口PreparedStatement

二,Statement的弊端

  1. 存在拼串操作,繁琐

  2. 存在SQL注入问题:利用某些系统没有对用户输入的数据进行充分的检查,而在用户输入数据中注入非法的SQL语句段或命令(如:SELECT user, password FROM user_table WHERE user=‘a’ OR 1 = ’ AND password = ’ OR ‘1’ = ‘1’) ,从而利用系统的SQL引擎完成恶意行为的做法。

    // 使用Statement的弊端:需要拼写sql语句,并且存在SQL注入的问题
    @Test
    public void testLogin() {
    	Scanner scan = new Scanner(System.in);
    	System.out.print("用户名:");
    	String userName = scan.nextLine();
    	System.out.print("密  码:");
    	String password = scan.nextLine();
    	// SELECT user,password FROM user_table WHERE USER = '1' or ' AND PASSWORD = '='1' or '1' = '1';
    	String sql = "SELECT user,password FROM user_table WHERE USER = '" + userName + "' AND PASSWORD = '" + password
    			+ "'";
    	User user = get(sql);
    	if (user != null) {
    		System.out.println("登陆成功!");
    	} else {
    		System.out.println("用户名或密码错误!");
    	}
    }
    

    对于Java而言,要防范SQL注入,只要用PreparedStatement取代 Statement就可以了

三,PreparedStatement 的增删改操作

  1. **概述:**PreparedStatement接口是Statement的子接口,它表示一条预编译过的SQL语句。PreparedStatement对象所代表的SQL语句中的参数用问号(?)来表示,调用PreparedStatement对象的setXxx()方法来设置这些参数,setXxx()方法有两个参数,第一个参数是要设置的SQL语句中的参数的索引(从 1 开始),第二个是设置的SQL语句中的参数的值

  2. 使用步骤

  • 获取连接对象

    Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/test","root","123456");
    
  • 编写SQL语句

    String st_class = "1004",st_num = "1003";
    String sql = "UPDATE student SET st_class = ? WHERE st_num = ?";
    
  • 预编译sql语句:可以通过调用Connection对象的**preparedStatement(String sql)**方法获取PreparedStatement的实例

    PreparedStatement ps = con.prepareStatement(sql);
    
  • 填充占位符

    ps.setString(1,st_class);
    ps.setString(2,st_num);
    
  • 执行操作

    ps.execute();
    
  • 资源关闭

    ps.close();
    con.close();
    
  1. PreparedStatement的优点

    • 代码的可读性和可维护性
    • 提高性能:DBServer会对预编译语句提供性能优化,下次调用时只要是相同的预编译语句就不需要编译,只要将参数直接传入编译过的语句执行代码中就会得到执行
    • 防止SQL注入
  2. Java与SQL对应数据类型转换表

    Java类型SQL类型
    booleanBIT
    byteTINYINT
    shortSMALLINT
    intINTEGER
    longBIGINT
    StringCHAR,VARCHAR,LONGVARCHAR
    byte arrayBINARY , VAR BINARY
    java.sql.DateDATE
    java.sql.TimeTIME
    java.sql.TimestampTIMESTAMP
  3. PreparedStatement 的增删改

    public static void main(String[] args) throws SQLException {
        // 获取连接对象
        Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/test","root","123456");
        // 编写SQL语句
        String st_class = "1004",st_num = "1003";
        String sql = "UPDATE student SET st_class = ? WHERE st_num = ?";
        // 预编译sql语句,获取PreparedStatement的实例
        PreparedStatement ps = con.prepareStatement(sql);
        // 填充占位符
        ps.setString(1,st_class);
        ps.setString(2,st_num);
        // 执行操作
        ps.execute();
        // 资源关闭
        ps.close();
        con.close();
    }
    
  4. PreparedStatement 的通用增删改操作

    public void update(String sql,Object...args) throws SQLException {
        // 获取连接对象
        Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/test","root","123456");
        // 预编译sql语句,获取PreparedStatement的实例
        PreparedStatement ps = con.prepareStatement(sql);
        // 填充占位符
        for (int i = 0;i < args.length;i++){
            ps.setObject(i + 1,args[i]);
        }
        // 执行操作
        ps.execute();
        // 资源关闭
        ps.close();
        con.close();
        resultSet.close();
    }
    

四,PreparedStatement 的查询操作

  1. ResultSet

    • 查询需要调用PreparedStatement 的 executeQuery() 方法,查询结果是一个ResultSet 对象

    • ResultSet 对象以逻辑表格的形式封装了执行数据库操作的结果集,ResultSet 接口由数据库厂商提供实现

    • ResultSet 返回的实际上就是一张数据表。有一个指针指向数据表的第一条记录的前面。

    • ResultSet 对象维护了一个指向当前数据行的游标,初始的时候,游标在第一行之前,可以通过 ResultSet 对象的 next() 方法移动到下一行。调用 next()方法检测下一行是否有效。若有效,该方法返回 true,且指针下移。相当于Iterator对象的 hasNext() 和 next() 方法的结合体。

    • 当指针指向一行时, 可以通过调用 getXxx(int index) 或 getXxx(int columnName) 获取每一列的值。

      • 例如: getInt(1), getString(“name”)
      • 注意:Java与数据库交互涉及到的相关Java API中的索引都从1开始。
    • ResultSet 接口的常用方法:

      • boolean next()

      • getString()

  2. 查询

    public static void main(String[] args) throws SQLException {
        // 获取连接对象
        Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/test","root","123456");
        // 编写SQL语句
        String st_class = "1004",st_num = "1003";
        String sql = "SELECT * FROM student WHERE st_num = ?";
        // 预编译sql语句,获取PreparedStatement的实例
        PreparedStatement ps = con.prepareStatement(sql);
        // 填充占位符
        ps.setString(1,st_num);
        // 执行操作
        ResultSet resultSet = ps.executeQuery(); //结果集
        // 结果处理
        while (resultSet.next()){ //返回boolean类型,判断下一条是否有数据,如果有数据,返回true,指针下移
            int id = resultSet.getInt(1);
            String name = resultSet.getString(2);
            String stClass = resultSet.getString(3);
            System.out.println(id+"--"+name+"--"+stClass);
        }
        // 资源关闭
        ps.close();
        con.close();
    }
    
  • 24
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值