JDBC高级

JDBC高级

1. PreparedStatement

1.1 PreparedStatement第一个案例 insert操作
public static void testInsert() {
    Connection connection = null;
    PreparedStatement statement = null;

    // 1. 获取数据库连接
    connection = JDBCUtil.getConnection();

    // 2. 准备SQL语句
    // ? 在SQL语句中是占位符,用于后期的数据添加
    String sql = "insert into javaee2009.student(id, name, age, info, score) VALUES (?,?,?,?,?)";

    try {
        // 3. 通过Connection对象 预处理SQL语句,获取PreparedStatement对象
        statement = connection.prepareStatement(sql);

        // 4. 给予当前SQL语句对应参数
        statement.setObject(1, 5);
        statement.setObject(2, "丢钥匙的航海中路彭于晏");
        statement.setObject(3, 6);
        statement.setObject(4, "他喵的就是一个ZZ");
        statement.setObject(5, -50);

        // 5. 执行SQL语句
        int i = statement.executeUpdate();
        System.out.println(i);

    } catch (SQLException e) {
        e.printStackTrace();
    } finally {
        JDBCUtil.close(statement, connection);
    }
}
1.2 PreparedStatement update操作
public static void testUpdate() {
    Connection connection = null;
    PreparedStatement statement = null;

    // 1. 获取数据库连接
    connection = JDBCUtil.getConnection();

    // 2. 准备SQL语句
    String sql = "update javaee2009.student set name = ?, age = ?, info = ?, score = ? where id = ?";

    try {
        // 3. 预处理SQL,获取PreparedStatement对象
        statement = connection.prepareStatement(sql);

        // 4. 赋值SQL语句对应参数
        statement.setObject(1, "尼古拉斯·赵四");
        statement.setObject(2, "66");
        statement.setObject(3, "你愁啥~~~");
        statement.setObject(4, "5");
        statement.setObject(5, "1");

        // 5. 执行SQL语句
        int i = statement.executeUpdate();
        System.out.println(i);
    } catch (SQLException e) {
        e.printStackTrace();
    } finally {
        JDBCUtil.close(statement, connection);
    }
}
1.3 PreparedStatment delete操作
public static void testDelete() {
    Connection connection = null;
    PreparedStatement statement = null;

    // 1. 获取数据库连接对象
    connection = JDBCUtil.getConnection();

    // 2. 准备SQL语句
    String sql = "delete from javaee2009.student where id = ?";

    try {
        // 3. 预处理SQL语句,获取PreparedStatement对象
        statement = connection.prepareStatement(sql);

        // 4. 赋值参数
        statement.setObject(1, 4);

        // 5. 执行SQL语句
        int i = statement.executeUpdate();
        System.out.println(i);
    } catch (SQLException e) {
        e.printStackTrace();
    } finally {
        JDBCUtil.close(statement, connection);
    }
}
1.4 PreparedStatement select One操作
public static void testSelectOne() {
    ResultSet resultSet = null;
    Connection connection = null;
    PreparedStatement statement = null;

    // 1. 获取数据库连接
    connection = JDBCUtil.getConnection();

    // 2. 准备SQL语句
    String sql = "select * from javaee2009.student where id = ?";

    try {
        // 3. 预处理SQL语句,得到PreparedStatement对象
        statement = connection.prepareStatement(sql);

        // 4. 赋值参数
        statement.setObject(1, 2);

        // 5. 执行SQL语句,得到ResultSet结果集对象
        resultSet = statement.executeQuery();

        // 6. 解析结果集得到Student对象
        Student student = null;

        while (resultSet.next()) {
            // 根据字段名字获取对应的数据,赋值给成员变量
            int id = resultSet.getInt("id");
            String name = resultSet.getString("name");
            int age = resultSet.getInt("age");
            String info = resultSet.getString("info");
            float score = resultSet.getFloat("score");

            student = new Student(id, name, age, info, score);
        }

        System.out.println(student);
    } catch (SQLException e) {
        e.printStackTrace();
    } finally {
        JDBCUtil.close(resultSet, statement, connection);
    }
}
1.5 PreparedStatement select All操作
public static void testSelectAll() {
    ResultSet resultSet = null;
    Connection connection = null;
    PreparedStatement statement = null;

    // 1. 获取数据库连接对象
    connection = JDBCUtil.getConnection();

    // 2. 准备SQL语句
    String sql = "select * from javaee2009.student";

    try {
        // 3. 预处理SQL语句。获取PreparedStatement对象
        statement = connection.prepareStatement(sql);

        // 4. 执行SQL语句。获取ResultSet结果集对象
        resultSet = statement.executeQuery();

        // 5. 解析结果集
        ArrayList<Student> studentList = new ArrayList<>();

        while (resultSet.next()) {
            int id = resultSet.getInt("id");
            String name = resultSet.getString("name");
            int age = resultSet.getInt("age");
            String info = resultSet.getString("info");
            float score = resultSet.getFloat("score");

            studentList.add(new Student(id, name, age, info, score));
        }

        for (Student student : studentList) {
            System.out.println(student);
        }
    } catch (SQLException e) {
        e.printStackTrace();
    } finally {
        JDBCUtil.close(resultSet, statement, connection);
    }
}

2. Statement和PreparedStatement对比

Statment执行的SQL语句为固定SQL语句,需要SQL语句在执行之前明确所有内容。
PreparedStatement执行的SQL语句,就可以后期赋值操作。
	1. 预处理SQL语句。告知MySQL数据库,这里目前需要执行一个SQL语句,参数还不确定,MySQL请准备。后期给予MySQL是对应参数,可以降低程序和数据库之间的数据交换量,提高效率。
	2. PreparedStatement可以有效的防止【SQL注入】
package com.qfedu.a_preparestatement;

import util.JDBCUtil;

import java.sql.*;

/*
SQL注入演示
 */
public class Demo2 {
    private static String userName = "苟磊";
    private static String password = "fdjsaklfjdklsajfl' or 1=1 -- ";

    public static void main(String[] args) {
        testStatement();
        testPreparedStatement();
    }

    public static void testStatement() {
        ResultSet resultSet = null;
        Statement statement = null;
        Connection connection = null;

        connection = JDBCUtil.getConnection();

        try {
            statement = connection.createStatement();

            String sql = "select * from javaee2009.person where userName = '" + userName + "' and password = '" + password + "'";

            resultSet = statement.executeQuery(sql);

            if (resultSet.next()) {
                System.out.println("Statement 登陆成功");
            } else {
                System.out.println("Statement 登陆失败");
            }

        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JDBCUtil.close(resultSet, statement, connection);
        }
    }

    public static void testPreparedStatement() {
        ResultSet resultSet = null;
        Connection connection = null;
        PreparedStatement statement = null;

        connection = JDBCUtil.getConnection();

        String sql = "select * from javaee2009.person where userName = ? and password = ?;";

        try {
            statement = connection.prepareStatement(sql);

            statement.setObject(1, userName);
            statement.setObject(2, password);

            resultSet = statement.executeQuery();

            if (resultSet.next()) {
                System.out.println("PreparedStatement 登陆成功");
            } else {
                System.out.println("PreparedStatement 登陆失败");
            }

        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JDBCUtil.close(resultSet, statement, connection);
        }
    }
}

3. PreparedStatement封装

3.1 功能分析和总结
对于修改方法 ==> update delete insert SQL语句
	1. 目标任务的SQL语句
	2. 目标任务SQL语句对应的参数个数

对于查询方法 ==> select SQL语句
	1. 目标任务的SQL语句
	2. 目标任务SQL语句对应的参数个数
	3. 【目标】数据类型 当前查询数据库数据行对应的是哪一个类的对象。

通用查询和修改方法。
	query
	update
3.2 技术点缺失分析
1. SQL语句中 ? 占位符个数如何获得???
	int getParameterCount(); 获取SQL语句参数个数
	【参数元数据】 MetaData
	
2. SQL语句对应的参数如何处理???
	a. 个数不定
	b. 类型多样
	Object... 
3.2.1 参数元数据提供参数个数
Connection connection = JDBCUtil.getConnection();
String sql = "select * from javaee2009.person where userName = ? and password = ?";

PreparedStatement statement = connection.prepareStatement(sql);

// 获取参数元数据
ParameterMetaData parameterMetaData = statement.getParameterMetaData();

System.out.println(parameterMetaData.getParameterCount());
JDBCUtil.close(statement, connection);
3.2.2 BaseDao Update方法封装
package util;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

public class BaseDao {
    /*
    完成一个通用的update查询方法。
     */
    /**
     * 通用update更新方法,用于处理insert update delete SQL语句
     *
     * @param sql        当前需要指定的目标SQL语句
     * @param parameters 当前SQL语句对应的参数,为Object类型不定长参数
     * @return 当前SQL语句执行对于数据库的影响行数
     * @throws SQLException SQL异常
     */
    public int update(String sql, Object... parameters) throws SQLException {
        // 1. 必要变量定义
        Connection connection = null;
        PreparedStatement statement = null;

        // 2. 获取数据库连接
        connection = JDBCUtil.getConnection();

        // 3. 预处理SQL语句,得到PreparedStatement对象。预处理SQL语句导致的异常
        // 非当前方法问题,是因为用户在传入方法参数时导致的错误
        statement = connection.prepareStatement(sql);

        // 4. 赋值参数
        // 4.1 获取当前SQL语句参数个数
        int parameterCount = statement.getParameterMetaData().getParameterCount();

        // 4.2 赋值SQL对应参数,利用for循环。赋值之前需要判断参数
        // 参数数组不能为null, 参数个数和数组容量一致, 参数个数不能为0
        if (parameters != null && parameterCount == parameters.length && parameterCount != 0) {
            for (int i = 0; i < parameterCount; i++) {
                statement.setObject(i + 1, parameters[i]);
            }
        }

        // 5. 执行SQL语句
        int affectedRows = statement.executeUpdate();

        // 6. 关闭资源
        JDBCUtil.close(statement, connection);

        return affectedRows;
    }
}

上一篇:scala中使用JDBC连接数据库


下一篇:C3p0数据库连接池技术