JDBC(五)PreparedStatement 详解

本文涉及的产品
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: PreparedStatement 是一个特殊的Statement对象,如果我们只是来查询或者更新数据的话,最好用PreparedStatement代替Statement,因为它有以下有点:简化Statement中的操作提高执行语句的性能可读性和可维护性更好安全性更好。

PreparedStatement 是一个特殊的Statement对象,如果我们只是来查询或者更新数据的话,最好用PreparedStatement代替Statement,因为它有以下有点:

  • 简化Statement中的操作
  • 提高执行语句的性能
  • 可读性和可维护性更好
  • 安全性更好。
    使用PreparedStatement能够预防SQL注入攻击,所谓SQL注入,指的是通过把SQL命令插入到Web表单提交或者输入域名或者页面请求的查询字符串,最终达到欺骗服务器,达到执行恶意SQL命令的目的。注入只对SQL语句的编译过程有破坏作用,而执行阶段只是把输入串作为数据处理,不再需要对SQL语句进行解析,因此也就避免了类似select * from user where name='aa' and password='bb' or 1=1的sql注入问题的发生。

Statement 和 PreparedStatement之间的关系和区别.

  • 关系:PreparedStatement继承自Statement,都是接口
  • 区别:PreparedStatement可以使用占位符,是预编译的,批处理比Statement效率高

创建一个PreparedStatement

PreparedStatement对象的创建也同样离不开 DriverManger.getConnect()对象,因为它也是建立在连接到数据库之上的操作。

connection = DriverManager.getConnection(url,user,password);
String sql = "update user set username=? where id = ?";
PreparedStatement preparedStatement = connection.prepareStatement(sql);

往PreparedStatement里写入参数

看上面那个sql 字符串,中间有几个?,它在这里有点占位符的意思,然后我们可以通过PreparedStatement的setString(),等方法来给占位符进行赋值,使得sql语句变得灵活。

            Class.forName("com.mysql.jdbc.Driver");
            connection = DriverManager.getConnection(url,user,password);
            String sql = "update user set username=? where id = ?";
            PreparedStatement preparedStatement = connection.prepareStatement(sql);

            preparedStatement.setString(1,"Fant.J");
            preparedStatement.setInt(2,27);

参数中的第一个参数分别是1和2,它代表的是第几个问号的位置。如果sql语句中只有一个问号,那就不用声明这个参数。

执行PreparedStatement

执行查询

如果是执行查询数据库的话,也像Statement对象执行excuteQuery()一样返回一个ResultSet结果集。这里就不多详述:

            String sql = "select * from user";
            PreparedStatement preparedStatement = connection.prepareStatement(sql);

            ResultSet resultSet = preparedStatement.executeQuery();

            while (resultSet.next()) {
                int id = resultSet.getInt("id");
                String username = resultSet.getString("username");
                String birthday = resultSet.getString("birthday");
                String sex = resultSet.getString("sex");
                String address = resultSet.getString("address");

                System.out.println("  " + username + " " + birthday + " " + sex
                        + " " + address);
            }
  Fant.J 2017-04-20 男 xxxx

复用PreparedStatement

什么叫复用,就是一次实例化,多次使用。

            preparedStatement.setString(1,"Fant.J");
            preparedStatement.setInt(2,27);

            int result = preparedStatement.executeUpdate();
            preparedStatement.setString(1,"Fant.J reUseTest");
            preparedStatement.setInt(2,27);
            preparedStatement.executeUpdate();

那如何在同一个PreparedStatement对象中进行查询操作呢

            String sql2 = "select * from user";

            ResultSet resultSet = preparedStatement.executeQuery(sql2);

            while (resultSet.next()) {
                int id = resultSet.getInt("id");
                String username = resultSet.getString("username");
                String birthday = resultSet.getString("birthday");
                String sex = resultSet.getString("sex");
                String address = resultSet.getString("address");

                System.out.println("  " + username + " " + birthday + " " + sex
                        + " " + address);
            }
  Fant.J reUseTest 2017-04-20 男 xxxx

完整代码

package com.jdbc;

import java.sql.*;

/**
 * Created by Fant.J.
 * 2018/3/3 13:35
 */
public class PreparedStatementTest {
    public static void main(String[] args) {
        String url = "jdbc:mysql://localhost:3306/user";
        String user = "root";
        String password = "root";

        Connection connection =null;
        try {
            Class.forName("com.mysql.jdbc.Driver");
            connection = DriverManager.getConnection(url,user,password);
            String sql = "update user set username=? where id = ?";
            PreparedStatement preparedStatement = connection.prepareStatement(sql);

            preparedStatement.setString(1,"Fant.J");
            preparedStatement.setInt(2,27);

            int result = preparedStatement.executeUpdate();
            preparedStatement.setString(1,"Fant.J reUseTest");
            preparedStatement.setInt(2,27);
            preparedStatement.executeUpdate();


            String sql2 = "select * from user";

            ResultSet resultSet = preparedStatement.executeQuery(sql2);

            while (resultSet.next()) {
                int id = resultSet.getInt("id");
                String username = resultSet.getString("username");
                String birthday = resultSet.getString("birthday");
                String sex = resultSet.getString("sex");
                String address = resultSet.getString("address");

                System.out.println("  " + username + " " + birthday + " " + sex
                        + " " + address);
            }


        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        }


    }
}

PreparedStatement性能分析

数据库解析SQL字符串需要时间,并为其创建查询计划。查询计划是分析数据库如何以最有效的方式执行查询。

如果为每个查询或数据库更新提交新的完整SQL语句,则数据库必须解析SQL,并为查询创建查询计划。通过重用现有的PreparedStatement,可以为后续查询重用SQL解析和查询计划。这通过减少每个执行的解析和查询计划开销来加速查询执行。

PreparedStatement有两个潜在的重用(复用)级别。
  • JDBC驱动程序重新使用PreparedStatement。
  • 数据库重用PreparedStatement。

首先,JDBC驱动程序可以在内部缓存PreparedStatement对象,从而重用PreparedStatement对象。这可能会节省一小部分PreparedStatement创建时间。

其次,高速缓存的解析和查询计划可能会跨Java应用程序(例如群集中的应用程序服务器)重复使用,并使用相同的数据库。


img_a7cf8cfd5b44b49b57a92e2db3b4188d.png
image.png
相关文章
|
5月前
|
Java 数据库连接 数据库
JDBC之Statement与PreparedStatement操作数据库对比
JDBC之Statement与PreparedStatement操作数据库对比
|
5月前
|
SQL Java 关系型数据库
Java与数据库连接技术JDBC关键核心之PreparedStatement以及SQL注入演示解决和原理
Java与数据库连接技术JDBC关键核心之PreparedStatement以及SQL注入演示解决和原理
41 0
|
6月前
|
SQL 流计算 API
实时计算 Flink版产品使用合集之ClickHouse-JDBC 写入数据时,发现写入的目标表名称与 PreparedStatement 中 SQL 的表名不一致如何解决
实时计算Flink版作为一种强大的流处理和批处理统一的计算框架,广泛应用于各种需要实时数据处理和分析的场景。实时计算Flink版通常结合SQL接口、DataStream API、以及与上下游数据源和存储系统的丰富连接器,提供了一套全面的解决方案,以应对各种实时计算需求。其低延迟、高吞吐、容错性强的特点,使其成为众多企业和组织实时数据处理首选的技术平台。以下是实时计算Flink版的一些典型使用合集。
75 0
|
6月前
|
SQL Java 关系型数据库
JDBC PreparedStatement 字段值为null导致TBase带宽飙升的案例分析
JDBC PreparedStatement 字段值为null导致TBase带宽飙升的案例分析
109 0
|
6月前
|
SQL 存储 Java
JDBC技术【封装JDBC工具类、Statement的使用、PreparedStatement的使用(重点)、ResultSet的使用】(二)-全面详解(学习总结---从入门到深化)
JDBC技术【封装JDBC工具类、Statement的使用、PreparedStatement的使用(重点)、ResultSet的使用】(二)-全面详解(学习总结---从入门到深化)
358 0
|
11月前
|
SQL 缓存 Java
JDBC中PreparedStatement常用操作实践
JDBC中PreparedStatement常用操作实践
278 1
|
SQL Java 数据库连接
JDBC快速入门(五)--PreparedStatement用法
JDBC快速入门(五)--PreparedStatement用法
104 0
|
Java 数据库连接
使用JDBC中的PreparedStatement批量插入
使用JDBC中的PreparedStatement批量插入
347 0
|
SQL 存储 缓存
JDBC使用PreparedStatement实现CRUD操作
JDBC使用PreparedStatement实现CRUD操作
157 0
|
SQL Java 数据库连接
JDBC学习(二):PreparedStatement初体验
JDBC学习(二):PreparedStatement初体验
JDBC学习(二):PreparedStatement初体验