PreparedStatement 对象详解★★★
PreparedStatement★★★
1、练习程序
练习1:用preparedstatement完成Insert编写
练习代码
import com.xy.MySQL.myMethods.JDBCUtils;
import java.sql.*;
import java.util.Date;
public class preparedStatementInsert {
public static void main(String[] args) {
Connection conn = null;
PreparedStatement pst = null;
ResultSet rs = null;
try{
conn = JDBCUtils.getConnection();
//接下来和statement有区别
//先写sql用于接下来的预编译(不执行),使用?占位符代替参数
String sql = "INSERT INTO users(id,name,password,email,birthday) VALUES(?,?,?,?,?)";//使用?占位符代替参数
pst = conn.prepareStatement(sql);//预编译SQL,需要先写SQL,但是不执行
//手动给上边的参数赋值
//语法为pst.set参数类型(参1,参2)
//其中参1是下标,从1开始,比如说下边的index为1代表给id赋值
pst.setInt(1,4);//id为4
pst.setString(2,"赵六");//name为赵六
pst.setString(3,"1234567");//name为赵六
pst.setString(4,"123456@qq.com");//name为赵六
/*注意点:
sql.Date 数据库用时 java.sql.Date()
util.Date Java用时 new Date().getTime() 获取时间戳
*/
pst.setDate(5,new java.sql.Date(new Date().getTime()));//import java.util.Date
/*
插入日期其实也可以用setString的方法,只不过这样插入的就是一行字符串了
原表的birthday部分的类型必须得是字符串类型
pst.setString(5,"1990-05-01");
*/
//直接执行SQL
int i = pst.executeUpdate();
if (i>0){
System.out.println("插入成功!");
}
}catch (SQLException e){
e.printStackTrace();
}finally {
JDBCUtils.release(conn,pst,null);
}
}
}
运行结果
练习2:用preparedstatement完成Delete编写
练习代码
import com.xy.MySQL.myMethods.JDBCUtils;
import java.sql.*;
public class preparedStatementDelete {
public static void main(String[] args) {
Connection conn = null;
PreparedStatement pst = null;
ResultSet rs = null;
try{
conn = JDBCUtils.getConnection();
//接下来和statement有区别
//先写sql用于接下来的预编译(不执行),使用?占位符代替参数
String sql = "DELETE FROM users WHERE id=?";//使用?占位符代替参数
pst = conn.prepareStatement(sql);//预编译SQL,需要先写SQL,但是不执行
//手动给上边的参数赋值
//语法为pst.set参数类型(参1,参2)
//其中参1是下标,从1开始,比如说下边的parameterIndex为1代表给id赋值
pst.setInt(1,4);//id为4
//直接执行SQL
int i = pst.executeUpdate();
if (i>0){
System.out.println("删除成功!");
}
}catch (SQLException e){
e.printStackTrace();
}finally {
JDBCUtils.release(conn,pst,null);
}
}
}
运行结果
练习3:用preparedstatement完成Update编写
练习代码
import com.xy.MySQL.myMethods.JDBCUtils;
import java.sql.*;
public class preparedStatementUpdate {
public static void main(String[] args) {
Connection conn = null;
PreparedStatement pst = null;
ResultSet rs = null;
try{
conn = JDBCUtils.getConnection();
//接下来和statement有区别
//先写sql用于接下来的预编译(不执行),使用?占位符代替参数
String sql = "UPDATE users SET name=? WHERE id=?";//使用?占位符代替参数
pst = conn.prepareStatement(sql);//预编译SQL,需要先写SQL,但是不执行
//手动给上边的参数赋值
//语法为pst.set参数类型(参1,参2)
//其中参1是下标,从1开始,比如说下边的parameterIndex为1代表给name赋值
pst.setString(1,"张三b");//name为张三b
pst.setInt(2,1);//id为1
//直接执行SQL
int i = pst.executeUpdate();
if (i>0){
System.out.println("修改成功!");
}
}catch (SQLException e){
e.printStackTrace();
}finally {
JDBCUtils.release(conn,pst,null);
}
}
}
运行结果
练习4:用preparedstatement完成Select编写
练习代码
import com.xy.MySQL.myMethods.JDBCUtils;
import java.sql.*;
public class preparedStatementSelect {
public static void main(String[] args) {
Connection conn = null;
PreparedStatement pst = null;
ResultSet rs = null;
try{
conn = JDBCUtils.getConnection();
//接下来和statement有区别
//先写sql用于接下来的预编译(不执行),使用?占位符代替参数
String sql = "SELECT * FROM users WHERE id=?";//使用?占位符代替参数
pst = conn.prepareStatement(sql);//预编译SQL,需要先写SQL,但是不执行
//手动给上边的参数赋值
//语法为pst.set参数类型(参1,参2)
//其中参1为占位符编号,从1开始,比如说下边的parameterIndex为1代表给id赋值
pst.setInt(1,2);//id为2
//直接执行SQL
rs = pst.executeQuery();
while (rs.next()) {
System.out.println("id="+rs.getInt("id"));
System.out.println("name="+rs.getString("name"));
System.out.println("password="+rs.getString("password"));
System.out.println("email="+rs.getString("email"));
System.out.println("birthday="+rs.getDate("birthday"));
}
}catch (SQLException e){
e.printStackTrace();
}finally {
JDBCUtils.release(conn,pst,rs);
}
}
}
运行结果
id为2处的表格内容
练习5:防止SQL注入测试
练习代码
import com.xy.MySQL.myMethods.JDBCUtils;
import java.sql.*;
public class 防止SQL注入测试 {
public static void main(String[] args) {
//正常登录
//login("张三","123456");
//sql注入
//login("'' or 1=1","'' or 1=1");//使用错误的登录信息无法获得用户信息
login("王五","123456");//使用正确的登录信息成功获得该用户信息
}
/**
* 登录业务
*/
public static void login(String userName, String password) {
Connection con = null;
PreparedStatement pst = null;
ResultSet rs = null;
try {
con = JDBCUtils.getConnection();
/*
PreparedStatement 防止SQL注入的本质:把传递进来的参数作为字符
假如其中存在转义字符,直接忽略掉,比如说 '会被直接转义
*/
String sql = "SELECT * FROM users WHERE `name`=? AND `password`=?";
pst = con.prepareStatement(sql);
pst.setString(1,userName);
pst.setString(2,password);
rs = pst.executeQuery();
while (rs.next()) {
System.out.println("id="+rs.getInt("id"));
System.out.println("name="+rs.getString("name"));
System.out.println("password="+rs.getString("password"));
System.out.println("email="+rs.getString("email"));
System.out.println("birthday="+rs.getDate("birthday"));
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
JDBCUtils.release(con,pst,rs);
}
}
}
运行结果
-
使用错误的登录信息
login("'' or 1=1","'' or 1=1");
如图所示,没有获得任何用户信息
-
使用正确的登录信息(表中存在的信息)
login("王五","123456");
如图所示,成功获取该用户的信息
2、总结
1.首先来看一下preparedstatement对象和Statement对象用法在步骤上的区别
-
statement对象
-
首先声明变量 con,st,rs
Connection con = null; Statement st = null; ResultSet rs = null;
-
获取连接,创建statement对象,定义带参数的sql语句,执行sql语句(try)
con = JDBCUtils.getConnection();//获取连接 st = con.createStatement();//创建statement对象 String sql = "UPDATE users SET birthday='1990-12-01' WHERE id=1";//定义带参sql int num = st.executeUpdate(sql);//执行sql语句
-
捕获异常(catch)
catch (SQLException e) { e.printStackTrace(); }
-
最后释放连接(finally)
finally{ JDBCUtils.release(con, st, rs); }
-
-
preparedstatement对象
-
首先声明变量 con,st,rs
Connection con = null; Statement st = null; ResultSet rs = null;
-
获取连接
con = JDBCUtils.getConnection();
-
之后就开始和statement对象有区别了
-
首先要写不带参的sql用于接下来的预编译(不执行),使用 ? 占位符代替参数,比如说:
String sql = "SELECT * FROM users WHERE id=?";
-
然后创建preparedstatement对象对SQL进行预编译(不执行)
pst = conn.prepareStatement(sql);
-
再然后手动给上边的不带参参数赋值,语法为
pst.set参数类型(参1,参2)
其中参1为占位符 ? 的位置,从1开始比如说下边的例子中,参1和参2分别为 1 和 2 代表给 ? 位置为 1 的 id 赋值为 2
pst.setInt(1,2)
-
最后执行sql语句,需要注意的是这里的执行不用带参
rs = pst.executeQuery();//不带参执行 rs = pst.executeQuery(sql);//带参执行
-
-
捕获异常和释放连接不再赘述
-
2.preparedstatement对象可以防止SQL注入
PreparedStatement 防止SQL注入的本质:把传递进来的参数作为字符
假如其中存在转义字符,直接忽略掉,比如说 ' 会被直接转义
3、setDate问题(存疑)
import com.xy.MySQL.myMethods.JDBCUtils;
import java.sql.*;
import java.util.Date;
public class preparedStatementInsert {
public static void main(String[] args) {
Connection conn = null;
PreparedStatement pst = null;
ResultSet rs = null;
try{
conn = JDBCUtils.getConnection();
//接下来和statement有区别
//先写sql用于接下来的预编译(不执行),使用?占位符代替参数
String sql = "INSERT INTO users(id,name,password,email,birthday) VALUES(?,?,?,?,?)";//使用?占位符代替参数
pst = conn.prepareStatement(sql);//预编译SQL,需要先写SQL,但是不执行
//手动给上边的参数赋值
//语法为pst.set参数类型(参1,参2)
//其中参1是下标,从1开始,比如说下边的index为1代表给id赋值
pst.setInt(1,4);//id为4
pst.setString(2,"赵六");//name为赵六
pst.setString(3,"1234567");//name为赵六
pst.setString(4,"123456@qq.com");//name为赵六
/*注意点:
sql.Date 数据库用时 java.sql.Date()
util.Date Java用时 new Date().getTime() 获取时间戳
*/
pst.setDate(5,new java.sql.Date(new Date().getTime()));//import java.util.Date
/*
插入日期其实也可以用setString的方法,只不过这样插入的就是一行字符串了
原表的birthday部分的类型必须得是字符串类型
pst.setString(5,"1990-05-01");
*/
//直接执行SQL
int i = pst.executeUpdate();
if (i>0){
System.out.println("插入成功!");
}
}catch (SQLException e){
e.printStackTrace();
}finally {
JDBCUtils.release(conn,pst,null);
}
}
}
sql.Date和java.Date完全不同,这个问题比较头疼,比如说
在上边这个练习中,我想插入一个自定义日期而不是当前日期,应该怎么办呢
没啥头绪,回看~~
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律