8. 使用PreparedStatement实现CRUD操作

8. 使用PreparedStatement实现CRUD操作

前言

在上一篇章我们使用了 PreparedStatement 解决了 SQL 注入问题,那么再具体深入一下,我们来看看 PreparedStatement 如何实现 增删查改 的 操作。

使用PreparedStatement实现CRUD操作

1. PreparedStatement的使用

通过PreparedStatement完成增、删、改、查

1.1 PreparedStatement介绍

  • 可以通过调用 Connection 对象的 preparedStatement(String sql) 方法获取 PreparedStatement 对象

    String sql = "select * from t_user where uname = ?"; // 设置SQL, 使用问号?设置查询的条件参数
    PreparedStatement preparedStatement = connection.prepareStatement(sql); // 获取preparedStatement
  • PreparedStatement 接口是 Statement 的子接口,它表示一条预编译过的 SQL 语句

  • PreparedStatement 对象所代表的 SQL 语句中的参数用问号(?)来表示,调用 PreparedStatement 对象的 setXxx() 方法来设置这些参数.

    setXxx() 方法有两个参数,第一个参数是要设置的 SQL 语句中的参数的索引(从 1 开始),第二个是设置的 SQL 语句中的参数的值

1.2 PreparedStatement vs Statement

  • 代码的可读性和可维护性。

  • PreparedStatement 能最大可能提高性能:

    • DBServer会对预编译语句提供性能优化。因为预编译语句有可能被重复调用,所以语句在被DBServer的编译器编译后的执行代码被缓存下来,那么下次调用时只要是相同的预编译语句就不需要编译,只要将参数直接传入编译过的语句执行代码中就会得到执行。
    • 在statement语句中,即使是相同操作但因为数据内容不一样,所以整个语句本身不能匹配,没有缓存语句的意义.事实是没有数据库会对普通语句编译后的执行代码缓存。这样每执行一次都要对传入的语句编译一次。
    • (语法检查,语义检查,翻译成二进制命令,缓存)
  • PreparedStatement 可以防止 SQL 注入

1.3 Java与SQL对应数据类型转换表

Java类型 SQL类型
boolean BIT
byte TINYINT
short SMALLINT
int INTEGER
long BIGINT
String CHAR,VARCHAR,LONGVARCHAR
byte   array BINARY  ,    VAR BINARY
java.sql.Date DATE
java.sql.Time TIME
java.sql.Timestamp TIMESTAMP

2.操作分析

  1. 注册驱动
  2. 获得连接
  3. 创建预编译sql语句对象
  4. 设置参数 执行
  5. 释放资源

3.实现

3.1 使用 PreparedStatement 完成数据插入

8. 使用PreparedStatement实现CRUD操作image-20210121090147924
/**
 * 使用 PreparedStatement   完成数据插入
 *
 * @throws Exception
 */
@Test
public void test08() throws Exception {
    //1.获取连接
    Connection connection = JdbcUtils.getConnection();

    //2.使用 PreparedStatement 完成数据插入
    //2.1 编写SQL语句: 插入一条数据
    String sql = "insert into t_user values(null,?,?,?)";
    //2.2 获取 PreparedStatement 并设置 参数
    PreparedStatement preparedStatement = connection.prepareStatement(sql); // 预编译sql语句
    preparedStatement.setString(1, "特朗普"); // 设置第一个问号? 参数
    preparedStatement.setString(2, "68");
    preparedStatement.setString(3, "0");
    //2.3 执行 SQL
    int i = preparedStatement.executeUpdate();
    System.out.println("插入的数据: " + i);

    //3.释放资源
    JdbcUtils.closeAll(preparedStatement, connection);

}

执行后,我们在 mysql 查询数据如下:

mysql> select * from t_user;
+----+-----------+------+------+
| id | uname     | age  | sex  |
+----+-----------+------+------+
|  1 | zs        |   18 |    1 |
|  2 | ls        |   20 |    0 |
|  3 | ww        |   23 |    1 |
|  4 | zl        |   24 |    1 |
|  5 | lq        |   15 |    0 |
|  6 | hh        |   12 |    0 |
|  7 | wzx       |   60 | NULL |
|  8 | lb        | NULL | NULL |
| 10 | 特朗普    |   68 |    0 |  -- 刚刚插入的数据
+----+-----------+------+------+
9 rows in set (0.00 sec)

mysql> 

3.2 使用 PreparedStatement 完成数据更新

8. 使用PreparedStatement实现CRUD操作image-20210122083019799
/**
 * 使用 PreparedStatement   完成数据更新
 *
 * @throws Exception
 */
@Test
public void test09() throws Exception {
    //1.获取连接
    Connection connection = JdbcUtils.getConnection();

    //2.使用 PreparedStatement 完成数据插入
    //2.1 编写SQL语句: 更新 id = 10 的数据
    String sql = "update t_user set uname = ? where id = 10";
    //2.2 获取 PreparedStatement 并设置 参数
    PreparedStatement preparedStatement = connection.prepareStatement(sql); // 预编译sql语句
    preparedStatement.setString(1, "拜登"); // 设置第一个问号? 参数

    //2.3 执行 SQL
    int i = preparedStatement.executeUpdate();
    System.out.println("更新的数据: " + i);

    //3.释放资源
    JdbcUtils.closeAll(preparedStatement, connection);

}

查询更新后的数据如下:

mysql> select * from t_user;
+----+--------+------+------+
| id | uname  | age  | sex  |
+----+--------+------+------+
|  1 | zs     |   18 |    1 |
|  2 | ls     |   20 |    0 |
|  3 | ww     |   23 |    1 |
|  4 | zl     |   24 |    1 |
|  5 | lq     |   15 |    0 |
|  6 | hh     |   12 |    0 |
|  7 | wzx    |   60 | NULL |
|  8 | lb     | NULL | NULL |
| 10 | 拜登   |   68 |    0 | -- 成功更新数据
+----+--------+------+------+
9 rows in set (0.00 sec)

mysql> 

3.3 使用 PreparedStatement 完成数据删除

8. 使用PreparedStatement实现CRUD操作image-20210122084327356
/**
 * 使用 PreparedStatement   完成数据删除
 *
 * @throws Exception
 */
@Test
public void test10() throws Exception {
    //1.获取连接
    Connection connection = JdbcUtils.getConnection();

    //2.使用 PreparedStatement 完成数据插入
    //2.1 编写SQL语句: 更新 id = 10 的数据
    String sql = "delete from t_user where id = ?";
    //2.2 获取 PreparedStatement 并设置 参数
    PreparedStatement preparedStatement = connection.prepareStatement(sql); // 预编译sql语句
    preparedStatement.setString(1, "10"); // 设置第一个问号? 参数

    //2.3 执行 SQL
    int i = preparedStatement.executeUpdate();
    System.out.println("删除的数据: " + i);

    //3.释放资源
    JdbcUtils.closeAll(preparedStatement, connection);

}

3.4 使用 PreparedStatement 查询一条数据

8. 使用PreparedStatement实现CRUD操作image-20210122084703413
/**
 * 使用 PreparedStatement   查询一条数据
 *
 * @throws Exception
 */
@Test
public void test11() throws Exception {
    //1.获取连接
    Connection connection = JdbcUtils.getConnection();

    //2.使用 PreparedStatement 完成数据插入
    //2.1 编写SQL语句: 查询 id = 8 的数据
    String sql = "select * from t_user where id = ?";
    //2.2 获取 PreparedStatement 并设置 参数
    PreparedStatement preparedStatement = connection.prepareStatement(sql); // 预编译sql语句
    preparedStatement.setString(1, "8"); // 设置第一个问号? 参数

    //2.3 执行 SQL
    ResultSet resultSet = preparedStatement.executeQuery();
    User user = null;
    while (resultSet.next()) {
        user = new User(resultSet.getInt("id"),
                resultSet.getString("uname"),
                resultSet.getString("age"),
                resultSet.getString("sex"));
    }

    System.out.println(user);

    //3.释放资源
    JdbcUtils.closeAll(preparedStatement, connection);

}

3.5 使用 PreparedStatement 查询多条数据

8. 使用PreparedStatement实现CRUD操作image-20210122085110940
/**
 * 使用 PreparedStatement   查询多条数据
 *
 * @throws Exception
 */
@Test
public void test12() throws Exception {
    //1.获取连接
    Connection connection = JdbcUtils.getConnection();

    //2.使用 PreparedStatement 完成数据插入
    //2.1 编写SQL语句: 查询 id = 8 的数据
    String sql = "select * from t_user";
    //2.2 获取 PreparedStatement 并设置 参数
    PreparedStatement preparedStatement = connection.prepareStatement(sql); // 预编译sql语句

    //2.3 执行 SQL
    ResultSet resultSet = preparedStatement.executeQuery();
    ArrayList<User> users = new ArrayList<>(); // 使用集合存储所有查询的数据

    while (resultSet.next()) {
        User user = new User(resultSet.getInt("id"),
                resultSet.getString("uname"),
                resultSet.getString("age"),
                resultSet.getString("sex"));
        users.add(user);
    }

    // 打印查询的数据
    for (User user : users) {
        System.out.println(user);
    }
    
    //3.释放资源
    JdbcUtils.closeAll(preparedStatement, connection);

}

4.小结

4.1步骤

  1. 注册驱动
  2. 获得连接
  3. 创建预编译sql语句对象
  4. 设置参数, 执行
  5. 释放资源

4.2API

  1. 创建预编译sql语句对象
connection.prepareStatement(String sql); //sql里面有参数, 先用?代替,进行占位
  1. 设置参数
prepareStatement.set类型(int 第几个问号,Object 值);
  1. 执行
Result result = prepareStatement.excuteQuery();  //执行查询 不传sql语句
int rows  = prepareStatement.excuteUpdate();  //执行增删改 不传sql语句

4.3注意事项

  1. ?只能占参数,说白了就是列的值

  2. ?从1开始计数

  3. 执行的时候不要传入sql语句


上一篇:使用docker安装elasticsearch,head插件,在es中crud


下一篇:初窥MyBatis-普通的CRUD操作