JDBC-01

1.1 JDBC的概述

1.1.1 什么是JDBC

JDBC(Java Data Base Connectivity,java数据库连接)

是一种用于执行SQL语句的Java API,由一组用Java语言编写的类和接口组成。
同时JDBC也是个商标名。

1.1.2 什么是数据库驱动

1.1.3 为什么学习JDBC

没有JDBC的时候,如果现在要开发一套系统,使用Java连接MySQL数据库,那么这时候Java程序员需要了解MySQL驱动API,如果使用Java连接Oracle数据库,那么这个时候Java程序员需要了解Oracle数据库驱动API。

1.2 JDBC的入门

1.2.1 JDBC的环境准备

在这里插入图片描述

1.2.2 入门案例

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

public class demo01{
    public static void main(String[] args) throws Exception{
        //1.加载驱动
        Class.forName("com.mysql.jdbc.Driver");
        //2.获得连接
        Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/emp","root","266531");
        //3.基本操作:执行SQL
        //3.1获得执行SQL语句的对象
        Statement statement = conn.createStatement();
        //3.2编写SQL语句
        String sql = "select * from emp";
        //3.3执行SQL
        ResultSet rs = statement.executeQuery(sql);
        //3.4遍历emp表
        while (rs.next()){
            System.out.print(rs.getInt("id")+" ");
            System.out.print(rs.getString("name")+" ");
            System.out.print(rs.getInt("salary")+" ");
            System.out.print(rs.getInt("age")+" ");
            System.out.println(rs.getInt("rid"));
        }
        //4.释放资源
       rs.close();
        statement.close();
        conn.close();
    }
}

2.1 JDBC的API详解

2.1.1 DriverManager:驱动管理类

2.1.1.1 作用一:注册驱动

在这里插入图片描述
这个方法可以完成驱动的注册,但是实际开发中一般不会使用这个方法完成驱动的注册。

原因:
如果需要注册驱动,使用DriverManager.registerDriver(new Driver());
但是查看源代码发现,在代码中有一段静态代码块,静态代码块已经调用了注册驱动的方法。

如果再手动调用该方法注册驱动,就会导致驱动被注册两次。实际开发中一般会采用:
在这里插入图片描述

2.1.1.2 作用二:获得连接

在这里插入图片描述
这个方法就是用来获得与数据库连接的方法:这个方法中有三个参数:

  • url:与数据库连接的路径
  • user:与数据库连接的用户名
  • password:与数据库连接的密码

主要关注url的写法
jdbc:mysql://localhost:3306/emp

  • jdbc:连接数据库的协议
  • mysql:是jdbc的子协议
  • localhost:要连接的MySQL数据库服务器的主机地址(连接是本机就可以写成localhost,如果连接的不是本机的,就需要写上连接主机的IP地址)
  • 3306:MySQL数据库服务器的端口号
  • emp:数据库名称

url如果连接的是本机的路径,可以简化为如下格式:
jdbc:mysql:///emp

2.1.2 Connection:与数据库连接对象

2.1.2.1 作用一:创建执行SQL语句的对象

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
执行SQL语句对象:

  • Statement:执行SQL
  • CallableStatement:执行数据库中存储过程
  • PreparedStatement:执行SQL,对SQL进行预处理,解决SQL注入漏洞。

2.1.2.2 作用二:管理事务

在这里插入图片描述
在这里插入图片描述

2.1.3 Statement:执行SQL

2.1.3.1 作用一:执行SQL

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 执行SQL的方法
    boolean execute(String sql); 用来执行查询,修改,添加,删除的SQL语句。
    1.ResultSet executeQuery(String sql); 用来执行查询(执行select语句)。
    2.Int executeUpdate(String sql); 用来执行修改,添加,删除的SQL语句,返回的int表示影响的行数

2.1.3.2 作用二:执行批处理

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

2.1.4 ResultSet:表示数据库结果集的数据表,通常通过执行查询数据库的语句生成。

通过select语句的查询结果。
只有查询语句才有结果集

2.1.4.1 结果集的遍历

在这里插入图片描述
代码实现:
在这里插入图片描述

2.1.4.2 结果集的获取

在这里插入图片描述

  • 结果集获取可以使用结果集中的:
    getXXX();方法通常都会有一个重载的方法。
    getXXX(int 列号)
    getXXX(String 列名)
    通常使用后者

2.2 JDBC的资源释放

JDBC程序执行结束后,将与数据库进行交互的对象释放掉,通常是ResultSet,Statement,Connection。

这几个对象尤其是Connection对象是非常稀有的。所以这个对象一定要做到尽量晚创建,尽早释放。

  • 将资源释放的代码写入到finally的代码块中。
  • 资源释放的代码应该写的标准

资源释放标准代码:

        if(rs!=null){
            try{
                rs.close();
            }catch (SQLException e){
                e.printStackTrace();
            }

            rs = null;
        }
        if(statement!=null){
            try{
                rs.close();
            }catch (SQLException e){
                e.printStackTrace();
            }

            rs = null;
        }
        if(conn!=null){
            try{
                rs.close();
            }catch (SQLException e){
                e.printStackTrace();
            }

            rs = null;
        }

2.3 JDBC的CRUD操作

2.3.1 保存操作代码实现

    public static void save() {
        Connection conn = null;
        Statement stmt = null;

        try {
            Class.forName("com.mysql.jdbc.Driver");
            conn = DriverManager.getConnection("jdbc:mysql:///emp", "root", "266531");
            stmt = conn.createStatement();
            String sql = "insert into emp values(null,'Spike',1500,4,5)";
            int num = stmt.executeUpdate(sql);
            if (num > 0) {
                System.out.println("保存用户成功!");
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (conn != null) {
                try {
                    conn.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
                conn = null;
            }

            if (stmt != null) {
                try {
                    stmt.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
                stmt = null;
            }
        }
    }

2.3.2 修改操作代码实现

    public static void change(){
        Connection conn = null;
        Statement stmt = null;
        try{
            Class.forName("com.mysql.jdbc.Driver");
            conn = DriverManager.getConnection("jdbc:mysql:///emp", "root", "266531");
            stmt = conn.createStatement();
            String sql="update emp set salary=5000 where name='Rarity'";
            int num = stmt.executeUpdate(sql);
            if(num>0){
                System.out.println("信息修改成功");
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            if(conn!=null){
                try{
                    conn.close();
                }catch (SQLException se){
                    se.printStackTrace();
                }
                conn=null;
            }
            if(stmt!=null){
                try{
                    stmt.close();
                }catch (SQLException se){
                    se.printStackTrace();
                }
                stmt=null;
            }
        }
    }

2.3.3 删除操作代码实现

2.3.4 查询操作代码实现

2.3.4.1 查询多条记录

3.1 JDBC的工具类的抽取

3.1.1 抽取一个JDBC 的工具类

因为传统JDBC的开发,注册驱动,获得连接,释放资源这些代码都是重复编写的。所以可以将重复的代码提取到一个类中来完成。

public class JDBCUtils {
    private static final String driverClassName;
    private static final String url;
    private static final String username;
    private static final String password;

    static{
        driverClassName = "com.mysql.jdbc.Driver";
        url="jdbc:mysql:///emp";
        username="root";
        password="266531";
    }

    /*注册驱动*/
    public static void loadDriver(){
        try {
            Class.forName(driverClassName);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
    /*获得连接的方法*/
    public static Connection getConnection(){
        Connection conn = null;
        try {
            loadDriver();
            conn = DriverManager.getConnection(url, username, password);
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
        return conn;
    }

    /*释放资源的方法*/
    public static void release(Statement stmt,Connection conn){
        if (conn != null) {
            try {
                conn.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
            conn = null;
        }

        if (stmt != null) {
            try {
                stmt.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
            stmt = null;
        }
    }
    public static void release(Statement stmt, Connection conn, ResultSet rs){
        if(conn!=null){
            try{
                conn.close();
            }catch (SQLException se){
                se.printStackTrace();
            }
            conn = null;
        }
        if (stmt!=null){
            try{
                stmt.close();
            }catch (SQLException se){
                se.printStackTrace();
            }
            stmt=null;
        }
        if (rs!=null){
            try{
                rs.close();
            }catch (SQLException se){
                se.printStackTrace();
            }
            rs=null;
        }
    }

3.2 JDBC的配置信息提取到配置文件

3.2.1 配置文件

  • 属性文件
    格式:扩展名是.properites
    内容:key=value
  • XML文件

3.2.2 提取信息到配置文件

  • 定义一个配置文件
    在这里插入图片描述

3.2.3 在工具类中解析属性文件

  • 获取到具体内容为常量赋值
        //获取属性文件中的内容:
        Properties properties  = new Properties();
        try {
            properties.load(new FileInputStream("src/db.properties"));
        } catch (IOException e) {
            e.printStackTrace();
        }

        driverClassName = properties.getProperty("driveClassName");
        url=properties.getProperty("url");
        username=properties.getProperty("username");
        password=properties.getProperty("password");

4.1 JDBC的SQL注入漏洞

4.1.1 什么是SQL注入漏洞

  • 输入用户名
    Rarity’ or ‘1=1 密码随意
    Rarity’ – 密码随意

在这里插入图片描述

4.1.2 JDBC的SQL注入漏洞分析

输入的用户名为:

  • aaa’ or '1=1
  • aaa’ –

原因:

  • 在变量中存在SQL的关键字
    or

    都是SQL中的关键字

4.1.3 JDBC的SQL注入漏洞解决:PreparedStatement

需要采用PreparedStatement对象解决SQL注入漏洞。这个对象会将SQL预先进行编译,使用?作为占位符。?所代表内容是SQL所固定。再次传入变量(包含SQL关键字)

易错点:已经过PrepareStatement预编译的sql语句执行时不必再传入sql

public class UserDao {
    public static void main(String[] args) {

        boolean login = login("Rarity"5000);
        System.out.println(login);

    }

    public static boolean login(String username,int salary) {
        Connection conn = null;
        PreparedStatement pstmt = null;
        ResultSet rs = null;
        try {
            conn = JDBCUtils.getConnection();
            String sql = "select * from emp where name = ? and salary = ?";
            pstmt = conn.prepareStatement(sql);
            pstmt.setString(1, username);
            pstmt.setInt(2, salary);
            rs = pstmt.executeQuery();     //此时这里面就不再加sql语句了
            if (rs.next()) {
                return true;
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            JDBCUtils.release(pstmt, conn, rs);
        }
        return false;
    }
/*    public static boolean login(String name,int salary){
        Connection conn = null;
        Statement stmt = null;
        ResultSet rs = null;
        try{
            conn = JDBCUtils.getConnection();
            stmt = conn.createStatement();
            String sql = "select salary from emp where name ='" + name +"' and salary =" + salary;
            rs  = stmt.executeQuery(sql);
            if (rs.next()){
                return true;
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            JDBCUtils.release(stmt,conn);
        }
        return false;
    }*/
}

4.1.4 PreparedStatement的CRUD操作

4.1.4.1 保存操作代码实现

    public static void saveUser(String name,String local){
        Connection conn = null;
        PreparedStatement pstmt = null;
        try{
            conn = JDBCUtils.getConnection();
            String sql = "insert into user values(null,?,?)";
            pstmt = conn.prepareStatement(sql);
            pstmt.setString(1,name);
            pstmt.setString(2,local);
            int num = pstmt.executeUpdate();
            if(num>0){
                System.out.println("用户信息保存成功");
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            JDBCUtils.release(pstmt,conn);
        }
        System.out.println("用户信息保存失败");
    }

4.1.4.2 修改操作代码实现

    public static void updateUser(int id,String name,String local){
        Connection conn = null;
        PreparedStatement pstmt = null;
        try{
            conn = JDBCUtils.getConnection();
            String sql = "update user set uname = ? ,local = ? where uno = ?";
            pstmt = conn.prepareStatement(sql);
            pstmt.setString(1,name);
            pstmt.setString(2,local);
            pstmt.setInt(3,id);
            int num = pstmt.executeUpdate();
            if(num > 0){
                System.out.println("信息修改完成");
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            JDBCUtils.release(pstmt,conn);
        }
    }

4.1.4.3 删除操作代码实现

    public static void deleteUser(int id){
        Connection conn = null;
        PreparedStatement pstmt = null;
        try{
            conn = JDBCUtils.getConnection();
            String sql = "delete from user where uno = ?";
            pstmt = conn.prepareStatement(sql);
            pstmt.setInt(1,id);
            int num = pstmt.executeUpdate();
            if(num>0){
                System.out.println("删除成功");
            }else{
                System.out.println("删除失败");
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            JDBCUtils.release(pstmt,conn);
        }
    }

4.1.4.4 查询操作代码实现

    public static void selectUser(int id){
        Connection conn = null;
        ResultSet rs = null;
        PreparedStatement pstmt = null;
        try{
            conn = JDBCUtils.getConnection();
            String sql = "select * from user where uno = ?";
            pstmt = conn.prepareStatement(sql);
            pstmt.setInt(1,id);
            rs = pstmt.executeQuery();
            if(rs.next()){
                System.out.println(rs.getInt("uno") + " " + rs.getString("uname") + " " + rs.getString("local"));
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            JDBCUtils.release(pstmt,conn,rs);
        }
    }

5.1 JDBC的批处理操作

5.1.1 什么是批处理

之前进行JDBC的操作的时候,都是一条SQL语句执行。现在如果使用批处理,可以将一批SQL一起执行。

5.1.2 批处理的基本使用

    public static void demo(){
        Connection conn = null;
        Statement stmt = null;
        try{
            conn = JDBCUtils.getConnection();
            stmt = conn.createStatement();
            //编写一批SQL语句:
            String sql1 = "create database test1";
            String sql2 = "use test1";
            String sql3 = "create table user(id int primary key auto_increment,name varchar(20))";
            String sql4 = "insert into user values(null,'Rarity')";
            String sql5 = "insert into user values(null,'TwilightSparkle')";
            String sql6 = "insert into user values(null,'FlutterShy')";
            //添加到批处理
            stmt.addBatch(sql1);
            stmt.addBatch(sql2);
            stmt.addBatch(sql3);
            stmt.addBatch(sql4);
            stmt.addBatch(sql5);
            stmt.addBatch(sql6);
            //执行批处理:
            stmt.executeBatch();
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            JDBCUtils.release(stmt,conn);
        }
    }

5.1.3 批量插入(使用PreparedStatement)

批处理参数:rewriteBatchStatements=true

在这里插入图片描述

6.1 JDBC-事务

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

    public static void tranfer(){
        Connection conn = null;
        PreparedStatement pstmt = null;
        try{
            conn = JDBCUtils.getConnection();

            //开启事务
            conn.setAutoCommit(false);

            String sql = "UPDATE Remainder SET money = money+ ? WHERE NAME= ?";
            pstmt = conn.prepareStatement(sql);
            pstmt.setDouble(1,-1000);
            pstmt.setString(2,"Rarity");
            pstmt.executeUpdate();

            pstmt.setDouble(1,1000);
            pstmt.setString(2,"TwilightSparkle");
            pstmt.executeUpdate();

            //提交事务
            conn.commit();

        }catch (Exception e){
            //如果出现异常,就进行回滚
            try {
                conn.rollback();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
            e.printStackTrace();
        }finally {
            JDBCUtils.release(pstmt,conn);
        }
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值