JDBC详解

目录

一、JDBC简介

 二、JDBC的快速入门

 三、DriverManager详解

 1. 注册驱动

 2.获取数据库连接

四、Connection详解

1.获取执行SQL的对象

2.事务管理 

 五、Statement详解

 六、ResultSet详解

ResultSet(结果集对象)作用:

获取查询结果

使用步骤 

 ResultSet案例

七、PreparedStatement详解

       PrepareStatement作用

       PrepareStatement用法步骤

       PreparedStatement的好处

       PreparedStatement的原理:


一、JDBC简介

  • JDBC就是用Java语言操作关系型数据库的一套API。
  • 全称:(Java DataBase Connectivity)Java数据库连接。

JDBC本质:同一套Java代码,操作不同类型的关系型数据库。 

  • 官方(sun公司)定义的一套操作所有关系型数据库的规则,即接口
  • 各个数据库厂商去实现这套接口,提供数据库驱动jar包
  • 我们可以使用这套接口(JDBC) 编程,真正执行的代码是驱动jar包中的实现类

 二、JDBC的快速入门

步骤:

①创建工程,导入驱动jar包

1. 配置: 

2. 导入jar包:

3. 右键点击jar包,将jar包添加到本项目中

 

②注册驱动

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

③获取连接

Connection conn = DriverManager.getConnection(url,username,password);

④定义sql语句

String sql = "update...";

⑤获取执行sql对象

Statement stmt = conn.creatStatement();

⑥执行sql

stmt.executeUpdate(sql);

⑦处理返回结果

⑧释放资源

package com.itheima.jdbc;

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

/*
* JDBC快速入门
*/
public class JDBCDemo {
    public static void main(String[] args) throws Exception {
        //1.注册驱动
        Class.forName("com.mysql.jdbc.Driver");

        //2.获取连接
        String url = "jdbc:mysql://127.0.0.1:3306/db1";//固定写法,只需修改db1数据库名来连接不通的数据库
        String username = "root";
        String password = "";
        Connection conn = DriverManager.getConnection(url, username, password);

        //3. 定义sql语句
        String sql = "update account set money = 2000 where id = 1";

        //4.获取执行sql的对象Statement
        Statement stmt = conn.createStatement();

        //5.执行sql
        int count = stmt.executeUpdate(sql);//受影响的行数

        //6.处理结果
        System.out.println(count);

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

}

 三、DriverManager详解

  •   DriverManager(驱动管理类)作用:
  • 1.注册驱动
  • 2.获取数据库连接

  1. 注册驱动

Class.forNae("com.mysql.jdbc.Driver");//可以省略不写

             查看Driver源代码:

tips:

  • MySQL5之后的驱动包,可以省略注册驱动的步骤
  • 自动加载jar包中 META-INF\services\java.sql.Driver文件中的驱动类

 2.获取数据库连接

static Connection getConnection(String url,String user,String password);

参数: 

       ①url:连接路径

        语法:jdbc:mysql://ip地址(域名):端口号/数据库名称?参数键值对1&参数键值对2...

        示例:jdbc:mysql://127.0.0.1:3306/db1

        细节:

  •  如果连接的是本机的mysql服务器,并且mysql服务默认端口是3306,则url可以简写为:jdbc:mysql://数据库名称?参数键值对
  • 配置useSSL=false参数,禁止安全连接方式,解决警告提示

        ② user:用户名

        ③password:密码

四、Connection详解

  •   Connection(数据库连接对象)作用:
  • 1.获取执行SQL的对象
  • 2.管理事务

1.获取执行SQL的对象

  •  执行普通SQL对象:

Statement createStatement() 

  •  预编译SQL的执行SQL对象:防止SQL注入

PrepareStatement prepareStatement(sql)

  • 执行存储过程的对象

CallableStatement prepareCall(sql) 

2.事务管理 

MySQL事务管理

开启事务:begin;/start transaction

提交事务:commit;

回滚事务:rollback;

MySQL默认自动提交事务

JDBC事务管理:Connection接口中定义了三个对应的方法

开启事务:setAutoCommit(boolean autoCommit):true为自动提交事务,false为手动提交事务

提交事务:commit{};

回滚事务:rollback();

    public static void main(String[] args) throws Exception {
        //1.注册驱动
        //Class.forName("com.mysql.cj.jdbc.Driver");//5版本之后的mysql不需要写,jar包中META-INF中有
        //2.获取连接:如果连接的是本机的mysql并且端口是默认的3306则可以简写
        String url = "jdbc:mysql:///db1?useSSL=false";//固定写法,只需修改db1数据库名来连接不通的数据库,?后是参数
        String username = "root";
        String password = "";
        Connection conn = DriverManager.getConnection(url, username, password);
        //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();


        //快捷键ctrl+alt+t
        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 e) {

            //回滚事务
            conn.rollback();
            e.printStackTrace();
        }

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

 五、Statement详解

  •  Statement作用:执行SQL语句

执行SQL语句

int executeUpdate(sql):执行DML、DDL语句

返回值:(1)DML语句影响的行数

               (2)DDL语句执行后,执行成功也可能返回0

ResultSet executeQuery(sql):执行DQL语句

返回值:ResultQuery结果集对象

/**
 * JDBC API详解:Statement
 */
public class JDBCDemo4_Statement {
    /**
     * 执行DML语句
     * @throws Exception
     */
    @Test
    public void testDML() throws Exception {
        //1.注册驱动
        //Class.forName("com.mysql.cj.jdbc.Driver");//5版本之后的mysql不需要写,jar包中META-INF中有
        //2.获取连接:如果连接的是本机的mysql并且端口是默认的3306则可以简写
        String url = "jdbc:mysql:///db1?useSSL=false";//固定写法,只需修改db1数据库名来连接不通的数据库,?后是参数
        String username = "root";
        String password = "";
        Connection conn = DriverManager.getConnection(url, username, password);

        //3. 定义sql语句
        String sql = "update account set money = 3000 where id = 5";

        //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();
    }

    /**
     * 执行DDL语句
     * @throws Exception
     */
    @Test
    public void testDDL() throws Exception {
        //1.注册驱动
        //Class.forName("com.mysql.cj.jdbc.Driver");//5版本之后的mysql不需要写,jar包中META-INF中有
        //2.获取连接:如果连接的是本机的mysql并且端口是默认的3306则可以简写
        String url = "jdbc:mysql:///db1?useSSL=false";//固定写法,只需修改db1数据库名来连接不通的数据库,?后是参数
        String username = "root";
        String password = "";
        Connection conn = DriverManager.getConnection(url, username, password);

        //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);
//        if(count>0){
//            System.out.println("修改成功!");
//        }else{
//            System.out.println("修改失败!");
//        }
        System.out.println(count);
        //7.释放资源
        stmt.close();
        conn.close();
    }
}

 六、ResultSet详解

  • ResultSet(结果集对象)作用:

        封装了DQL查询语句的结果

        ResultSet stmt.executeQuery(sql):执行DQL语句,返回ResultSet对象

  • 获取查询结果

boolean next():(1)将光标从当前位置向前移动一行

                        (2)判断当前行是否为有效行

返回值:

        ture:有效行,当前行有数据

        false:无效行,当前行没有数据

xxx getXxx(参数) :获取数据

        xxx:数据类型;如:int getInt(参数);String getString(参数);

        参数:

                int:列的编号,从1开始

                String:列的名称

  • 使用步骤: 

        1.游标向下移动一行,并判断该行是否有数据:next()

        2.获取数据:getXxx(参数)

//循环判断游标是否是最后一行末尾

while(rs.next(()){

        //获取数据

        rs.getXxx(参数);

 /**
     * 执行DQL语句
     * @throws Exception
     */
    @Test
    public void testResultSet() throws Exception {
        //1.注册驱动
        //Class.forName("com.mysql.cj.jdbc.Driver");//5版本之后的mysql不需要写,jar包中META-INF中有
        //2.获取连接:如果连接的是本机的mysql并且端口是默认的3306则可以简写
        String url = "jdbc:mysql:///db1?useSSL=false";//固定写法,只需修改db1数据库名来连接不通的数据库,?后是参数
        String username = "root";
        String password = "";
        Connection conn = DriverManager.getConnection(url, username, password);

       //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(1);
//            String name = rs.getString(2);
//            double money = rs.getDouble(3);
//
//            System.out.println(id);
//            System.out.println(name);
//            System.out.println(money);
//            System.out.println("-------");
//        }

        //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.rollback();
    }

 ResultSet案例

需求:查询account账户表数据,封装在Account对象中,并且存储到ArrayList集合中

//1.注册驱动
        //Class.forName("com.mysql.cj.jdbc.Driver");//5版本之后的mysql不需要写,jar包中META-INF中有
        //2.获取连接:如果连接的是本机的mysql并且端口是默认的3306则可以简写
        String url = "jdbc:mysql:///db1?useSSL=false";//固定写法,只需修改db1数据库名来连接不通的数据库,?后是参数
        String username = "root";
        String password = "";
        Connection conn = DriverManager.getConnection(url, username, password);

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

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

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


        //创建集合
        List<Account> list = new ArrayList<>();

        //6.1 rs.next()光标向下移动一行并且判断当前行是否有数据
        while(rs.next()){
            Account account = new Account();

            //6.2获取数据    getXxx()
            int id = rs.getInt("id");
            String name = rs.getString("name");
            double money = rs.getDouble("money");

            //赋值
            account.setId(id);
            account.setName(name);
            account.setMoney(money);

            //存入集合
            list.add(account);

        }
        System.out.println(list);
        //7.释放资源
        rs.close();
        stmt.close();
        conn.rollback();
    }

七、PreparedStatement详解

  • PrepareStatement作用:

        预编译SQL语句并执行:防止SQL注入问题

  • SQL注入

        SQL注入是通过操作输入来修改事先定义好的SQL语句,用以达到执行代码对服务器进行攻击的方法。

  • 原sql语句:
select * from tb_user where username = 'zhangsan' and password = '123'
  • 通过操作输入来修改事先定义好的SQL语句,使之语意发生改变: 
select * from tb_user where username = '呵呵呵' and password = '' or '1' = '1' 
  • 采用API:PreparedStatement后:在pstmt.setXxx时将传入的值进行转义,将转义后的内容当成文本的形式传入。
 -- ' or '1' = '1
select * from tb_user where username = 'hfkjsfhskj'  and password = '\' or \'1\' = \'1'
  • PrepareStatement用法步骤:

        ①获取PreparedStatement对象

//SQl语句中的参数值,使用?占位符替代
String sql = "select * from user where username = ? and password = ? ";

//通过Connection对象获取,并传入对应的sql语句
PreparedStatement pstmt = conn.prepareStatement(sql);

        ②设置参数值

PreparedStatement对象:setXxx(参数1,参数2):给?赋值
Xxx:数据类型;如setInt(参数1,参数2)

参数:

        参数1:?的位置编号,从1开始

        参数2:?的值

        ③ 执行sql

//不再需要传递sql
executeUpdate();
executeQuery();

防止SQL注入用法示例: 

@Test
    public void testPreparedStatement() throws Exception {

        //2.获取连接:如果连接的是本机的mysql并且端口是默认的3306则可以简写
        String url = "jdbc:mysql:///db1?useSSL=false";//固定写法,只需修改db1数据库名来连接不通的数据库,?后是参数
        String username = "root";
        String password = "";
        Connection conn = DriverManager.getConnection(url, username, password);


        //接受用户名和密码
        String name = ",,,,";
        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();
        //判断登录是否成功
        if(rs.next()){
            System.out.println("登陆成功!!!");
        }else{
            System.out.println("登陆失败!");
        }


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

需求:完成用户登陆

select * from tb_user where username = "张三" and password = '123';
/**
     * 演示sql注入
     * @throws Exception
     */
    @Test
    public void testLogin_Inject() throws Exception {

        //2.获取连接:如果连接的是本机的mysql并且端口是默认的3306则可以简写
        String url = "jdbc:mysql:///db1?useSSL=false";//固定写法,只需修改db1数据库名来连接不通的数据库,?后是参数
        String username = "root";
        String password = "";
        Connection conn = DriverManager.getConnection(url, username, password);


        //接受用户名和密码
        String name = "shhiiii";
        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("登陆失败!");
        }
    }
  • PreparedStatement的好处:

        1.预编译SQL,性能高

        2.防止SQL注入:将敏感字符义

①PreparedStatement预编译功能开启:useServerPrepStmts=true 

②配置MySQL执行日志(重启mysql服务后生效)

 log-output=FILE
  general-log=1
  general_log_file="G:\MySQL\mysql.log"
  slow-query-log=1
  slow_query_log_file="G:\MySQL\mysql_show.log"
  long_query_time=2

  •   PreparedStatement的原理:

  •  1.在获取PreparedStatement对象时,将sql语句发送给mysql服务器进行检查,编译(这些步骤比较耗时)
  •  2.执行时就不用再进行这些步骤了,速度更快
  •  3.如果sql模板一样,则只需要进行一次检查、编译
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值