JDBC PreparedStatement接口

238 阅读5分钟

@[TOC]

PreparedStatement 接口

1.1 继承结构与作用:

PreparedStatement 是 Statement 接口的子接口,继承于父接口中所有的方法。它是一个预编译的 SQL 语句

1.2 PreparedSatement 的执行原理

1)因为有预先编译的功能,提高 SQL 的执行效率。 2)可以有效的防止 SQL 注入的问题,安全性更高。

1.3 Connection 创建 PreparedStatement 对象

Connection 接口中的方法 描述 PreparedStatement prepareStatement(String sql) 指定预编译的 SQL 语句,SQL 语句中使用占位符? 创建一个语句对象

1.4 PreparedStatement 接口中的方法:

PreparedStatement 接口中的方法 描述 int executeUpdate() 执行 DML,增删改的操作,返回影响的行数。 ResultSet executeQuery() 执行 DQL,查询的操作,返回结果集

1.5 PreparedSatement 的好处

1.prepareStatement()会先将 SQL 语句发送给数据库预编译。PreparedStatement 会引用着预编译后的结果。可以多次传入不同的参数给 PreparedStatement 对象并执行。减少 SQL 编译次数,提高效率。 2.安全性更高,没有 SQL 注入的隐患。 3.提高了程序的可读性

1.6 使用 PreparedStatement 的步骤:

1)编写 SQL 语句,未知内容使用?占位:"SELECT * FROM user WHERE name=? AND password=?"; 2)获得 PreparedStatement 对象 3)设置实际参数:setXxx(占位符的位置, 真实的值) 4)执行参数化 SQL 语句 5)关闭资源

PreparedStatement 中设置参数的方法 描述 void setDouble(int parameterIndex, double x) 将指定参数设置为给定 Java double 值。 void setFloat(int parameterIndex, float x) 将指定参数设置为给定 Java REAL 值。 void setInt(int parameterIndex, int x) 将指定参数设置为给定 Java int 值。 void setLong(int parameterIndex, long x) 将指定参数设置为给定 Java long 值。 void setObject(int parameterIndex, Object x) 使用给定对象设置指定参数的值。 void setString(int parameterIndex, String x) 将指定参数设置为给定 Java String 值。

 使用 PreparedStatement 改写上面的登录程序,看有没有 SQL 注入的情况 package com.itheima;

import com.itheima.utils.JdbcUtils; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.Scanner;

/**

  • 使用 PreparedStatement */ public class Demo8Login { //从控制台上输入的用户名和密码 public static void main(String[] args) throws SQLException { Scanner sc = new Scanner(System.in); System.out.println("请输入用户名:"); String name = sc.nextLine(); System.out.println("请输入密码:"); String password = sc.nextLine(); login(name, password); }

/**

  • 登录的方法

  • @param name

  • @param password */ private static void login(String name, String password) throws SQLException { Connection connection = JdbcUtils.getConnection(); //写成登录 SQL 语句,没有单引号 String sql = "select * from user where name=? and password=?"; //得到语句对象 PreparedStatement ps = connection.prepareStatement(sql); //设置参数ps.setString(1, name); ps.setString(2,password); ResultSet resultSet = ps.executeQuery(); if (resultSet.next()) { System.out.println("登录成功:" + name); } else { System.out.println("登录失败"); } //释放资源,子接口直接给父接口JdbcUtils.close(connection,ps,resultSet); } }

1.7 表与类的关系

1.7 .1案例:使用 PreparedStatement 查询一条数据,封装成一个学生 Student 对象

package com.itheima;

import com.itheima.entity.Student; import com.itheima.utils.JdbcUtils;

import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; public class Demo9Student { public static void main(String[] args) throws SQLException { //创建学生对象 Student student = new Student();

Connection connection = JdbcUtils.getConnection(); PreparedStatement ps = connection.prepareStatement("select * from student where id=?"); //设置参数ps.setInt(1,2); ResultSet resultSet = ps.executeQuery(); if (resultSet.next()) { //封装成一个学生对象student.setId(resultSet.getInt("id")); student.setName(resultSet.getString("name")); student.setGender(resultSet.getBoolean("gender")); student.setBirthday(resultSet.getDate("birthday")); } //释放资源JdbcUtils.close(connection,ps,resultSet);

//可以数据System.out.println(student); } }

1.7 .2案例:将多条记录封装成集合 List,集合中每个元素是一个 JavaBean 实体类

 需求: 查询所有的学生类,封装成 List返回 代码:

package com.itheima;

import com.itheima.entity.Student; import com.itheima.utils.JdbcUtils;

import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.List;

public class Demo10List { public static void main(String[] args) throws SQLException { //创建一个集合 List students = new ArrayList<>(); Connection connection = JdbcUtils.getConnection(); PreparedStatement ps = connection.prepareStatement("select * from student"); //没有参数替换 ResultSet resultSet = ps.executeQuery(); while(resultSet.next()) { //每次循环是一个学生对象 Student student = new Student(); //封装成一个学生对象student.setId(resultSet.getInt("id"));

student.setName(resultSet.getString("name")); student.setGender(resultSet.getBoolean("gender")); student.setBirthday(resultSet.getDate("birthday")); //把数据放到集合中students.add(student); } //关闭连接JdbcUtils.close(connection,ps,resultSet); //使用数据 for (Student stu: students) { System.out.println(stu); } } }

1.8 PreparedStatement 执行 DML 操作

package com.itheima;

import com.itheima.utils.JdbcUtils; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException;

public class Demo11DML { public static void main(String[] args) throws SQLException { //insert(); //update(); delete(); }

//插入记录 private static void insert() throws SQLException { Connection connection = JdbcUtils.getConnection(); PreparedStatement ps = connection.prepareStatement("insert into student values(null,?,?,?)"); ps.setString(1,"小白龙"); ps.setBoolean(2, true); ps.setDate(3,java.sql.Date.valueOf("1999-11-11")); int row = ps.executeUpdate(); System.out.println("插入了" + row + "条记录"); JdbcUtils.close(connection,ps); }

//更新记录: 换名字和生日 private static void update() throws SQLException { Connection connection = JdbcUtils.getConnection(); PreparedStatement ps = connection.prepareStatement("update student set name=?, birthday=? where id=?"); ps.setString(1,"黑熊怪"); ps.setDate(2,java.sql.Date.valueOf("1999-03-23")); ps.setInt(3,5); int row = ps.executeUpdate(); System.out.println("更新" + row + "条记录"); JdbcUtils.close(connection,ps); }

//删除记录: 删除第 5 条记录 private static void delete() throws SQLException { Connection connection = JdbcUtils.getConnection(); PreparedStatement ps = connection.prepareStatement("delete from student where id=?"); ps.setInt(1,5); int row = ps.executeUpdate(); System.out.println("删除了" + row + "条记录"); JdbcUtils.close(connection,ps); } }

第9节 JDBC 事务的处理 之前我们是使用 MySQL 的命令来操作事务。接下来我们使用 JDBC 来操作银行转账的事务。

2.1 准备数据

CREATE TABLE account ( id INT PRIMARY KEY AUTO_INCREMENT, NAME VARCHAR(10), balance DOUBLE ); -- 添加数据 INSERT INTO account (NAME, balance) VALUES ('Jack', 1000), ('Rose', 1000);

2.2 API 介绍

Connection 接口中与事务有关的方法 说明 void setAutoCommit(boolean autoCommit) 参数是 true 或 false 如果设置为 false,表示关闭自动提交,相当于开启事务 void commit() 提交事务 void rollback() 回滚事务

2.3 开发步骤

1)获取连接 2)开启事务 3)获取到 PreparedStatement 4)使用 PreparedStatement 执行两次更新操作 5)正常情况下提交事务 6)出现异常回滚事务 7)最后关闭资源 案例代码 package com.itheima;

import com.itheima.utils.JdbcUtils; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException;

public class Demo12Transaction {

//没有异常,提交事务,出现异常回滚事务 public static void main(String[] args) {

//1) 注册驱动 Connection connection = null; PreparedStatement ps = null; try { //2) 获取连接 connection = JdbcUtils.getConnection(); //3) 开启事务connection.setAutoCommit(false); //4) 获取到 PreparedStatement //从 jack 扣钱 ps = connection.prepareStatement("update account set balance = balance - ? where name=?"); ps.setInt(1, 500); ps.setString(2,"Jack"); ps.executeUpdate(); //出现异常System.out.println(100 / 0); //给 rose 加钱 ps = connection.prepareStatement("update account set balance = balance + ? where name=?"); ps.setInt(1, 500); ps.setString(2,"Rose"); ps.executeUpdate(); //提交事务connection.commit(); System.out.println("转账成功"); } catch (Exception e) { e.printStackTrace(); try { //事务的回滚connection.rollback(); } catch (SQLException e1) { e1.printStackTrace(); } System.out.println("转账失败"); } finally { //7) 关闭资源JdbcUtils.close(connection,ps); }

} }