当前位置: 首页 > news >正文

JDBC对数据的增删改查操作:从Statement到PrepareStatement

目录

一 . Statement简介

二. 通过Statement添加数据

1. 创建表

2. 通过Statement添加数据

a. 获取连接

b. 获取Statement对象

c. 定义SQL语句

d. 执行SQL语句

e. 关闭资源

3. 通过Statement修改数据

 4. 通过Statement删除数据

三. PreparedStatement的使用(重点)

1. 介绍

2. PreparedStatement的预编译

3. 通过PreparedStatement添加数据

4. 通过PreparedStatement修改数据

5. 通过PreparedStatement删除数据


前言

本文来讲解statementproperstatement的相关用法
上一节的最后一个JDBC工具类是非常重要的,要先把它实现了,因为后面会直接调用外面自己写的JDBC工具类
如果还不清楚这个的,就先看上一篇文章
传送门:JDBC连接

个人主页:艺杯羹

一 . Statement简介

作用:用于执行静态SQL语句
Statement接口特点:
用于执行静态 SQL 语句并返回它所生成结果的对象。 由 createStatement 创建,用于发送简单的 SQL 语句(不支持动态绑定
可以使用Statement来实现对数据库的增删改查操作,也就是数据操纵语言DML

注意:
由于Statement对象是一个执行静态SQL语句的对象,所以该对象存在SQL注入风险
后面会专门讲解SQL注入风险是什么。SQL注入会导致数据风险

JDBC中三种Statement对象

  • Statement:用于执行静态 SQL 语句
  • PreparedStatement:用于执行预编译SQL语句
  • CallableStatement:用于执行数据库存储过程

一般用Statement和PreparedStatement(更常用)

二. 通过Statement添加数据

1. 创建表

这里先创建一个表,之后就会使用这个数据库表

create table students (-- 学生 id,自增主键studentid int(11) not null auto_increment,-- 学生姓名,最大长度 30 字符studentname varchar(30) default null,-- 学生年龄studentage int(11) default null,-- 将 studentid 设为主键primary key (studentid)
) engine=InnoDB default charset=utf8mb4;

2. 通过Statement添加数据

因为将要用到Connection(用于连接) 和 Statement(用于执行SQL语句),这两个类都会抛出异常
所以会用到try --- catch来捕获,finally来关闭
因为我们上一节已经实现了JDBC工具类,接下来的操作很多都会用到JDBC工具类

a. 获取连接

connection = JdbcUtils.getConnection();

b. 获取Statement对象

statement = connection.createStatement();

c. 定义SQL语句

-- 如果写字符的话,在SQL中是要加单引号的
-- 所以字符串的写法为:'"zifuchaun1"'
-- 外面是单引号,里面再加双引号表示是字符串
String sql = "insert into students values(default,'"+studentname+"',"+studentage+")";

d. 执行SQL语句

-- 如果sql有结果集返回,那么返回值为true
-- 如果没有结果集返回,则返回false
boolean execute = statement.execute(sql);

e. 关闭资源

-- 使用JDBC工具类来关闭statement和connection
-- 要先关闭statement 后关闭connection
JdbcUtils.closeResource(statement,connection);

 完整代码

public class StatementTest {// 添加用户public void insertStudent(String studentname,int studentage){Connection connection = null;Statement statement = null;try{// 获取Connection对象connection = JdbcUtils.getConnection();// 获取Statement对象statement = connection.createStatement();// 定义需要执行的SQL语句String sql = "insert into users values(default,'"+studentname+"',"+studentage+")";// 执行SQL,返回boolean值,如果sql有结果集返回// 那么返回值为true,如果没有结果集返回,则返回false。boolean execute = statement.execute(sql);System.out.println(execute);}catch(Exception e){e.printStackTrace();}finally{// 关闭资源JdbcUtils.closeResource(statement,connection);}}
}

无数据

执行 

StatementTest ts = new StatementTest();
ts.insertStudent("LuoYi", 18);

3. 通过Statement修改数据

 public void updateStudent(int id,String name,int age){Connection connection = null;Statement statement = null;try{// 获取连接对象connection = JdbcUtils.getConnection();// 获取Statement对象statement = connection.createStatement();// 定义sql语句String sql ="update students set studentname = '"+name+"', studentage = "+age+" where studentid = "+id+"";// 执行sql语句int i = statement.executeUpdate(sql);System.out.println(i);}catch(Exception e){e.printStackTrace();}finally{// 关闭资源// 先关闭statement再关闭ConnectionJdbcUtils.closeResource(statement,connection);}}

执行

StatementTest ts = new StatementTest();
// 将id为1的人,修改名字和年龄
ts.updateStudent(1, "WangSiYa", 16);

回数据库看数据

 4. 通过Statement删除数据

// 通过id来删除元素
public void deleteStudentById(int id){Connection connection =null;Statement statement = null;try{// 获取数据库连接connection = JdbcUtils.getConnection();// 获取Statement对象statement = connection.createStatement();// 定义执行删除语句String sql = "delete from students where studentid="+id;// 执行sqlint i = statement.executeUpdate(sql);System.out.println(i);}catch(Exception e){e.printStackTrace();}finally{// 关闭资源JdbcUtils.closeResource(statement,connection);}}

执行

StatementTest ts = new StatementTest();
ts.deleteStudentById(1);

回DataDrip看结果

三. PreparedStatement的使用(重点)

1. 介绍

Statement 和 PreparedStatement 的用法都是用于执行SQL语句
PreparedStatement具有预编译SQL语句能力因此比 Statement 对象的效率更高
还实现了动态的参数绑定防止了SQL注入
所以后续一般是使用PrepareStatement来执行SQL

PreparedStatement对象的特点总结如下:

PreparedStatement
继承 Statement 接口
效率高
支持动态绑定参数
具备 SQL 预编译能力
可防止 SQL 注入

2. PreparedStatement的预编译

我们一般来执行SQL的时候,一般都是会多次执行某一个语句,所以只会修改里面个别的值
预编译,就会将执行过的SQL操作进行类似备份的操作,那么下次只要修改值就可以,这样效率自然就比没有预编译的Statement要高了
所谓预编译语句就是将这类语句中的值用占位符替代,可以视为将 sql 语句模板化或者说参数化预编译语句的优势在于:一次编译、多次运行省去了解析优化等过程;此外预编译语句能防止 sql 注入
接下来看看,是怎么实现的

3. 通过PreparedStatement添加数据

?:占位符
?是PreparedStatement对象中的绑定参数的占位符。问号的位置是从1开始计数

public class PreparedStatementTest {public void insertStudent(String ame,int age){Connection connection = null;PreparedStatement ps = null;try{// 获取数据库连接connection = JdbcUtils.getConnection();// 定义Sql。?是PreparedStatement对象中的绑定参数的占位符。问号的位置是从1开始计数的String sql = "insert into students values(default,?,?)";// 创建PreparedStatement对象ps = connection.prepareStatement(sql);// 完成参数的绑定ps.setString(1, name);ps.setInt(2, age);// 返回更新的行数int i = ps.executeUpdate();System.out.println(i);}catch(Exception e){e.printStackTrace();}finally{// 关闭资源JdbcUtils.closeResource(ps,connection);}}
}

4. 通过PreparedStatement修改数据

// 根据用户ID修改用户姓名与年龄public void updateUsersById(int id,String name,int age){Connection connection = null;PreparedStatement ps = null;try{// 获取数据库连接对象connection = JdbcUtils.getConnection();// 创建PreparedStatement对象ps = connection.prepareStatement("update students set studentname = ?,studentage=? where studentid = ?");// 参数绑定ps.setString(1,studentname);ps.setInt(2,studentage);ps.setInt(3,studentid);// 执行SQL语句// 返回行数int i = ps.executeUpdate();System.out.println(i);}catch(Exception e){e.printStackTrace();}finally{// 关闭资源JdbcUtils.closeResource(ps,connection);}}

5. 通过PreparedStatement删除数据

// 根据用户ID删除指定用户public void deleteUsersById(int id){Connection conn = null;PreparedStatement ps = null;try{// 获取数据库连接对象conn = JdbcUtils.getConnection();//创建PreparedStatement对象ps = conn.prepareStatement("delete from students where studentid = ? ");// 绑定参数ps.setInt(1,id);// 执行SQLint i = ps.executeUpdate();System.out.println(i);}catch (Exception e){e.printStackTrace();}finally{// 关闭资源JdbcUtils.closeResource(ps,conn);}}

四. 总结

到目前为止相信你会使用Statement和PrepareStatement来对数据库进行增删改查的操作了,希望对你有所帮助😊

相关文章:

  • Jupyter Notebook 中切换/使用 conda 虚拟环境的方式(解决jupyter notebook 环境默认在base下面的问题)
  • C语言文件操作完全手册:读写·定位·实战
  • 机器学习第二篇 多变量线性回归
  • go中map和slice非线程安全
  • Hive学习
  • 画布交互系统深度优化:从动态缩放、小地图到拖拽同步的全链路实现方案
  • 【Pandas】pandas DataFrame truediv
  • Android RecyclerView 多布局场景下的设计思考:SRP 与 OCP 的权衡与优化
  • 基于扣子(Coze.cn)与火山引擎构建高性能智能体的实践指南
  • Docker:重塑应用开发与部署的未来[特殊字符]
  • Codeforces Round 1019 (Div. 2)
  • 简述大疆无人机对接
  • 媒体发稿攻略,解锁新闻发稿成长新高度
  • 数据库介绍
  • 多台电脑切换解决方案:KVM 切换器
  • 解决 MongoDB 查询中的 `InvalidMongoDbApiUsageException` 错误
  • 外商在国内宣传 活动|发布会|参展 邀请媒体
  • C++进阶--二叉搜索树
  • 万字长文 | Apache SeaTunnel 分离集群模式部署 K8s 集群实践
  • 【Spring】依赖注入的方式:构造方法、setter注入、字段注入
  • 经济日报刊文:如何破除“内卷式”竞争
  • 受贿超8.22亿,新疆维吾尔自治区党委原副书记李鹏新一审被判死缓
  • 《哪吒2》延长放映至5月31日,当前全球票房已超157亿
  • 旁白丨无罪后领到国家赔偿,一位退休教师卸下了“包袱”
  • 俄乌就不打击民用基础设施释放对话信号
  • 第八届进博会将致力于打造“五个高”,为展商增值赋能