JDBC

JDBC 概述

什么是JDBC

JDBC(Java Data Base Connectivity) 是 Java 访问数据库的标准规范

是一种用于执行SQL语句的Java API,它由一组用Java语言编写的类和接口组成

JDBC的作用

可以为多种关系数据库提供统一访问,使我们使用一套代码就可以操作所有的关系型数据库。

JDBC 原理

JDBC是接口,驱动是接口的实现,没有驱动将无法完成数据库连接,从而不能操作数据库。

每个数据库厂商都需要提供自己的驱动,用来连接自己公司的数据库,也就是说驱动一般都由数据库生产厂商提供。

在这里插入图片描述

总结:JDBC就是由sun公司定义的一套操作所有关系型数据库的规则(接口),而数据库厂商需要实现这套接口,提供数据库驱动jar包,我们可以使用这套接口编程,真正执行的代码是对应驱动包中的实现类。

JDBC 开发

数据准备
-- 创建 jdbc_user表
CREATE TABLE jdbc_user (
id INT PRIMARY KEY AUTO_INCREMENT ,
username VARCHAR(50),
PASSWORD VARCHAR(50),
birthday DATE
);

-- 添加数据
INSERT INTO jdbc_user (username, PASSWORD,birthday)
VALUES('admin1', '123','1991/12/24'),
('admin2','123','1995/12/24'),
('test1', '123','1998/12/24'),
('test2', '123','2000/12/24');
MySql驱动包

将MySQL驱动包添加到Libraries,创建新项目时配置jar包库

API使用
public class JDBCDemo03 {
    public static void main(String[] args) throws Exception {
        //1.注册驱动
        // 从 JDBC3 开始可以不用注册驱动而直接使用 
        // Class.forName 这句话可以省略
        Class.forName("com.mysql.jdbc.Driver");
        
        //2.获取连接 url,用户名, 密码
        // Connection 接口,代表一个连接对象,具体的实现类由数据库的厂商实现
        String url = "jdbc:mysql://localhost:3306/db4";
        Connection con = DriverManager.getConnection(url, "root", "123456");
        
        //3.获取 Statement对象
        // Statement 代表一条语句对象,用于发送SQL语句给服务器,用于执行静态 SQL语句并返回它所生成结果的对象
        Statement statement = con.createStatement();
        
        //4.执行创建表操作
        String sql = "create table test01(id int, name varchar(20),age int);";
        
        //5.增删改操作 使用executeUpdate,增加一张表
        int i = statement.executeUpdate(sql);        
        //6.返回值是受影响的函数
        System.out.println(i);
       
        //7.关闭流
        statement.close();
        con.close();
    }
}
对URL的详细说明
jdbc:mysql://localhost:3306/db4?characterEncoding=UTF-8

JDBC规定url的格式由三部分组成,每个部分中间使用冒号分隔

  • 第一部分是协议 jdbc,这是固定的;
  • 第二部分是子协议,就是数据库名称,连接mysql数据库,第二部分是mysql;
  • 第三部分是由数据库厂商规定的,我们需要了解每个数据库厂商的要求
    • mysql的第三部分分别由数据库服务器的IP地址(localhost)、端口号(3306),以及要使用的数据库名称组成
处理结果集 ResultSet

只有在进行查询操作的时候,才会处理结果集

public class JDBCDemo04 {
    public static void main(String[] args) throws SQLException {
        //1.注册驱动 可以省略
        
        //2.获取连接
        String url = "jdbc:mysql://localhost:3306/db4";
        Connection con = DriverManager.getConnection(url, "root", "123456");
        
        //3.获取 Statement对象
        Statement statement = con.createStatement();
        String sql = "select * from jdbc_user";
        //执行查询操作,返回的是一个 ResultSet 结果对象
        ResultSet resultSet = statement.executeQuery(sql);
        
        //4.处理结果集
        //使用while循环
        while(resultSet.next()){
            //获取id
            int id = resultSet.getInt("id");
            //获取姓名
            String username = resultSet.getString("username");
            //获取生日
            Date birthday = resultSet.getDate("birthday");
            System.out.println(id + " = " +username + " : " + birthday);
        }
        
        //5.关闭连接
        // 释放原则:先开的后关,后开的先关
        resultSet.close();
        statement.close();
        con.close();
    }
}
JDBC工具类

什么时候自己创建工具类?

  • 如果一个功能经常用到,建议把这个功能做成一个工具类,可以在不同的地方重用
  • “获得数据库连接”操作,将在以后的增删改查所有功能中都存在,可以封装工具类JDBCUtils,提供获取连接对象的方法,从而达到代码的重复利用

工具类包含的内容

  • 可以把几个字符串定义成常量:用户名,密码,URL,驱动类
  • 得到数据库的连接:getConnection()
  • 关闭所有打开的资源
/**
* JDBC 工具类
*/
public class JDBCUtils {
    
    //1. 定义字符串常量, 记录获取连接所需要的信息
    public static final String DRIVERNAME = "com.mysql.jdbc.Driver";
    public static final String URL = "jdbc:mysql://localhost:3306/db4?characterEncoding=UTF-8";
    public static final String USER = "root";
    public static final String PASSWORD = "123456";
    
    //2. 静态代码块, 随着类的加载而加载
	static{
        try {
        //注册驱动
        Class.forName(DRIVERNAME);
        } catch (ClassNotFoundException e) {
        e.printStackTrace();
        }
	}

    //3.获取连接的静态方法
	public static Connection getConnection(){
        try {
            //获取连接对象
            Connection connection = DriverManager.getConnection(URL, USER, PASSWORD);
            //返回连接对象
            return connection;
            } catch (SQLException e) {
            e.printStackTrace();
            return null;
        }
	}

    //4.关闭资源的方法
	public static void close(Connection con, Statement st){
    	if(con != null && st != null){
            try {
                st.close();
                con.close();
            } catch (SQLException e) {
            	e.printStackTrace();
            }
		}
	}
	
    public static void close(Connection con, Statement st, ResultSet rs){
		if(rs != null){
            try {
            	rs.close();
            } catch (SQLException e) {
            	e.printStackTrace();
            }
		}
		close(con,st);
	}
}

SQL注入问题

sql注入案例:用户登陆
public class TestLogin01 {
    /**
    * 用户登录案例
    * 使用 Statement字符串拼接的方式完成查询
    * @param args
    */
    public static void main(String[] args) throws SQLException {
        //1.获取连接
        Connection connection = JDBCUtils.getConnection();
        
        //2.获取Statement
        Statement statement = connection.createStatement();
        
        //3.获取用户输入的用户名和密码
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入用户名: ");
        String name = sc.nextLine();
        
        System.out.println("请输入密码: ");
        String pass = sc.nextLine();
        System.out.println(pass);
        
        //4.拼接Sql,执行查询
        String sql = "select * from jdbc_user " +
        "where username = " + " '" + name +"' " +" and password = " +" '" + pass +"'";
        System.out.println(sql);
        ResultSet resultSet = statement.executeQuery(sql);
        
        //5.处理结果集,判断结果集是否为空
        if(resultSet.next()){
        	System.out.println("登录成功! 欢迎您: " + name);
        }else {
        	System.out.println("登录失败!");
        }
        
        //6.释放资源
        JDBCUtils.close(connection,statement,resultSet);
    }
}
SQL注入演示
-- 填写一个错误的密码
-- Sql注入方式: 123' or '1'=’1
SELECT * FROM jdbc_user WHERE username = 'tom' AND PASSWORD = '123' OR '1' = '1';
问题分析
  • 什么是SQL注入?

    • 我们让用户输入的密码和 SQL 语句进行字符串拼接
    • 用户输入的内容作为了 SQL 语句语法的一部分,改变了原有 SQL 真正的意义,以上问题称为 SQL 注入
  • 如何实现的注入

    • 根据用户输入的数据,拼接处的字符串

    • select * from jdbc_user where username = 'abc' and password = 'abc' or '1'='1'
      name='abc' and password='abc' 为假 '1'='1' 真
      相当于 select * from user where true=true; 查询了所有记录
      
  • 如何解决

    • 要解决 SQL 注入就不能让用户输入的密码和我们的 SQL 语句进行简单的字符串拼接

预处理对象

PreparedStatement 接口介绍
  • PreparedStatement 是 Statement 接口的子接口,继承于父接口中所有的方法,它是一个预编译的 SQL 语句对象
  • 预编译:是指SQL语句被预编译,并存储在 PreparedStatement 对象中,然后可以使用此对象多次高效地执行该语句
PreparedStatement 特点
  • 因为有预先编译的功能,提高 SQL 的执行效率
  • 可以有效的防止 SQL 注入的问题,安全性更高
使用PreparedStatement的步骤
public class TestLogin02 {
    /**
    * 使用预编译对象 PrepareStatement 完成登录案例
    * @param args
    * @throws SQLException
    */
    
    public static void main(String[] args) throws SQLException {
        //1.获取连接
        Connection connection = JDBCUtils.getConnection();
        
        //2.获取Statement
        Statement statement = connection.createStatement();
        
        //3.获取用户输入的用户名和密码
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入用户名: ");
        String name = sc.nextLine();
        
        System.out.println("请输入密码: ");
        String pass = sc.nextLine();
        System.out.println(pass);
        
        //4.获取 PrepareStatement 预编译对象
        //4.1 编写SQL 使用 ? 占位符方式
        String sql = "select * from jdbc_user where username = ? and password = ?";
        PreparedStatement ps = connection.prepareStatement(sql);
        //4.2 设置占位符参数
        ps.setString(1,name);
        ps.setString(2,pass);
        
        //5. 执行查询 处理结果集
        ResultSet resultSet = ps.executeQuery();
        if(resultSet.next()){
        	System.out.println("登录成功! 欢迎您: " + name);
        }else{
    		System.out.println("登录失败!");
    	}
        
    	//6.释放资源
    	JDBCUtils.close(connection,statement,resultSet);
    }
}
Statement 与 PreparedStatement的区别?
  • Statement用于执行静态SQL语句,在执行时必须指定一个事先准备好的SQL语句
  • PrepareStatement是预编译的SQL语句对象,语句中可以包含动态参数“?”,在执行时可以为“?”动态设置参数值
  • PrepareStatement可以减少编译次数提高数据库性能
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值