栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

JDBC-API详解

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

JDBC-API详解

目录

1.DiverManager

(1)注册

 (2)连接

2.Connection

 (1)事务管理:

3.Statement

 (1)执行DML、DDL

4.ResultSet

(1)代码测试

(2)案例:

5.PreparedStatement

(1) SQL注入演示:

(2)解决SQL注入

 (3)原理(如何预编译,如何防止sql注入)


1.DiverManager

PS:本文以JDK11为标准

(1)注册

 但是我们上一篇笔记里是这样获取驱动的:

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

这是为什么呢?,其实可以点到Driver的源码:

 (注意一下新版本的idea推荐的是com.mysql.cj.jdbc.Driver,而不是老套的com.mysql.jdbc.Driver)

 实质上这里有个静态代码块,而根据已学的知识,这个静态代码块会随着类的加载自动进行,不需要调什么方法,就可以注册上了。

不过5.0之后class这一行不写也没事,因为:

有对应文件然后读取,会自己做这个操作

 

 (2)连接

2.Connection

 

 (1)事务管理:

public class JDBCDemo3_Connection {

    public static void main(String[] args) throws Exception {
        //1. 注册驱动
        //Class.forName("com.mysql.jdbc.Driver");
        //2. 获取连接:如果连接的是本机mysql并且端口是默认的 3306 可以简化书写
        String url = "jdbc:mysql:///db1?useSSL=false";
        String username = "root";
        String p = "1234";
        Connection conn = DriverManager.getConnection(url, username, p);
        //3. 定义sql
        String sql1 = "update account set money = 3000 where id = 1";
        String sql2 = "update account set money = 3000 where id = 2";
        //4. 获取执行sql的对象 Statement
        Statement stmt = conn.createStatement();




        try {
            // 开启事务
            conn.setAutoCommit(false);
            //5. 执行sql
            int count1 = stmt.executeUpdate(sql1);//受影响的行数
            //6. 处理结果
            System.out.println(count1);
            int i = 3/0;
            //5. 执行sql
            int count2 = stmt.executeUpdate(sql2);//受影响的行数
            //6. 处理结果
            System.out.println(count2);

            // 提交事务
            conn.commit();
        } catch (Exception throwables) {
            // 回滚事务
            conn.rollback();
            throwables.printStackTrace();
        }



        //7. 释放资源
        stmt.close();
        conn.close();
    }
}

(2)获取对象——在其他知识点中融合体现

3.Statement

 (1)执行DML、DDL
public class JDBCDemo4_Statement {

    
    @Test
    public void testDML() throws  Exception {
       //1. 注册驱动
       //Class.forName("com.mysql.jdbc.Driver");
       //2. 获取连接:如果连接的是本机mysql并且端口是默认的 3306 可以简化书写
       String url = "jdbc:mysql:///db1?useSSL=false";
       String username = "root";
       String p = "1234";
       Connection conn = DriverManager.getConnection(url, username, p);
       //3. 定义sql
       String sql = "update account set money = 3000 where id = 1";
       //4. 获取执行sql的对象 Statement
       Statement stmt = conn.createStatement();
       //5. 执行sql
       int count = stmt.executeUpdate(sql);//执行完DML语句,受影响的行数
       //6. 处理结果
       //System.out.println(count);
        if(count > 0){
            System.out.println("修改成功~");
        }else{

            System.out.println("修改失败~");
        }
       //7. 释放资源
       stmt.close();
       conn.close();

   }



    
    @Test
    public void testDDL() throws  Exception {
        //1. 注册驱动
        //Class.forName("com.mysql.jdbc.Driver");
        //2. 获取连接:如果连接的是本机mysql并且端口是默认的 3306 可以简化书写
        String url = "jdbc:mysql:///db1?useSSL=false";
        String username = "root";
        String p= "1234";
        Connection conn = DriverManager.getConnection(url, username, p);
        //3. 定义sql
        String sql = "drop database db2";
        //4. 获取执行sql的对象 Statement
        Statement stmt = conn.createStatement();
        //5. 执行sql
        int count = stmt.executeUpdate(sql);//执行完DDL语句,可能是0
        //6. 处理结果
        //System.out.println(count);
       
        System.out.println(count);

        //7. 释放资源
        stmt.close();
        conn.close();

    }

}
(2)执行DML

在resultset案例中体现.

4.ResultSet

 

(1)代码测试
public class JDBCDemo5_ResultSet {

    
    @Test
    public void testResultSet() throws  Exception {
       //1. 注册驱动
       //Class.forName("com.mysql.jdbc.Driver");
       //2. 获取连接:如果连接的是本机mysql并且端口是默认的 3306 可以简化书写
       String url = "jdbc:mysql:///db1?useSSL=false";
       String username = "root";
       String p= "1234";
       Connection conn = DriverManager.getConnection(url, username, p);

       //3. 定义sql
        String sql = "select * from account";

        //4. 获取statement对象
        Statement stmt = conn.createStatement();

        //5. 执行sql
        ResultSet rs = stmt.executeQuery(sql);

        //6. 处理结果, 遍历rs中的所有数据
        // 6.1 光标向下移动一行,并且判断当前行是否有数据
        while (rs.next()){
            //6.2 获取数据  getXxx()
            int id = rs.getInt("id");
            String name = rs.getString("name");
            double money = rs.getDouble("money");

            System.out.println(id);
            System.out.println(name);
            System.out.println(money);

            System.out.println("--------------");

        }


        //7. 释放资源
        rs.close();
        stmt.close();
        conn.close();
    }




}

(2)案例:

   

public static void main(String[] args) throws Exception {
        //1. 注册驱动
        Class.forName("com.mysql.jdbc.Driver");//这个没办法我的Jar包就是老的,你要换一个jar包此案向,今天就算了
        //2. 获取连接:如果连接的是本机mysql并且端口是默认的 3306 可以简化书写
        String url = "jdbc:mysql:///dbTest?useSSL=false";
        String username = "root";
        String p = "***";
        Connection conn = DriverManager.getConnection(url, username, p);

        //3. 定义sql
        String sql = "select * from emp";

        //4. 获取statement对象
        Statement stmt = conn.createStatement();

        //5. 执行sql
        ResultSet rs = stmt.executeQuery(sql);

        //创建数组
        ArrayList emps = new ArrayList<>();

        //6. 处理结果, 遍历rs中的所有数据
        // 6.1 光标向下移动一行,并且判断当前行是否有数据
        while (rs.next()){
            //6.2 获取数据  getXxx()
            int id = rs.getInt("id");
            String name = rs.getString("ename");
            double money = rs.getDouble("salary");
            String date =rs.getString("joindate");
            Emp emp = new Emp();
            emp.setEname(name);
            emp.setId(id);
            emp.setJoindate(date);
            emp.setSalary(money);
            emps.add(emp);
            //System.out.println("--------------");
        }
        for (Emp emp : emps) {
            System.out.println(emp.toString());
        }

        //7. 释放资源
        rs.close();
        stmt.close();
        conn.close();
    }

5.PreparedStatement

(1) SQL注入演示:
    @Test
    public void testLogin_Inject() throws  Exception {
        //2. 获取连接:如果连接的是本机mysql并且端口是默认的 3306 可以简化书写
        String url = "jdbc:mysql:///db1?useSSL=false";
        String username = "root";
        String p = "1234";
        Connection conn = DriverManager.getConnection(url, username, p);

        // 接收用户输入 用户名和密码
        String name = "hfkjsfhskj";
        String pwd = "' or '1' = '1";

        String sql = "select * from tb_user where username = '"+name+"' and password = '"+pwd+"'";
        System.out.println(sql);
        // 获取stmt对象
        Statement stmt = conn.createStatement();
        // 执行sql
        ResultSet rs = stmt.executeQuery(sql);

        // 判断登录是否成功
        if(rs.next()){
            System.out.println("登录成功~");
        }else{
            System.out.println("登录失败~");
        }

        //7. 释放资源
        rs.close();
        stmt.close();
        conn.close();
    }

注意,这里为什么能登录上呢,我们把name pwd代入sql后来解析一下:

select * from tb_user where username = '123' and password = '' or '1' = '1'

首先不管你用户名输的对不对,and后面连接的password=''(空)肯定是错的,而后面Or的1=1肯定是对的,所以其实就是以前学过的逻辑表达式: (x&false)| true =true

即:select * from tb_user where true

——》就是全部都可以了呀

(2)解决SQL注入

        // 接收用户输入 用户名和密码

        String name = "zhangsan";

        String pwd = "' or '1' = '1";

        // 定义sql

        String sql = "select * from tb_user where username = ? and password = ?";

        // 获取pstmt对象

        PreparedStatement pstmt = conn.prepareStatement(sql);

        // 设置?的值

        pstmt.setString(1,name);

        pstmt.setString(2,pwd);

        // 执行sql

        ResultSet rs = pstmt.executeQuery();

那他又是怎么解决的呢?

是因为在set的时候他会进行转义,比如'机器就明白你想传递一个单引号,那就/',保持他的原义,而不会和password里面语法上的单引号混淆,就会把pwd作为整体看待了。

 (3)原理(如何预编译,如何防止sql注入)

 日志上就很明显:

不开启就是这样:

 开启有prepare的预编译:

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1024392.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号