> 文档中心 > <JDBC>使用PreparedStatement实现CRUD操作:你真的get到了吗?

<JDBC>使用PreparedStatement实现CRUD操作:你真的get到了吗?

在这里插入图片描述
🛒本文收录与专栏:《JDBC》专栏
📢专栏目的是解释JDBC的关键点,与各位一路同行,会持续输出,欢迎免费订阅!!

✨所能拯救我们的,唯有灵魂、哲学与大爱✨

在这里插入图片描述

目录

  • 一、介绍
  • 二、PreparedStatement
    • 🔥Java与SQL对应数据类型转换表
    • 🔥使用PreparedStatement实现增、删、改操作
    • 🔥使用PreparedStatement实现查询操作
  • 三、ResultSet
    • 🔥ResultSetMetaData
  • 四、资源的释放

一、介绍

java.sql包中有 3 个接口分别定义了对数据库的调用的不同方式:

  • Statement:用于执行静态 SQL 语句并返回它所生成结果的对象
  • PrepatedStatement:SQL 语句被预编译并存储在此对象中,可使用此对象多次高效地执行该语句
  • CallableStatement:用于执行 SQL 存储过程

下面是流程图:
在这里插入图片描述
其中Statement操作数据库需要拼写sql语句,并且存在SQL注入的问题,为防止SQL注入问题,使用PreparedStatement取代就可以了
在这里插入图片描述
下面也会对ResultSet进行讲解

public class StatementTest {// 使用Statement的弊端:需要拼写sql语句,并且存在SQL注入的问题@Testpublic void testLogin() {Scanner scan = new Scanner(System.in);System.out.print("用户名:");String userName = scan.nextLine();System.out.print("密   码:");String password = scan.nextLine();// SELECT user,password FROM user_table WHERE USER = '1' or ' AND PASSWORD = '='1' or '1' = '1';String sql = "SELECT user,password FROM user_table WHERE USER = '" + userName + "' AND PASSWORD = '" + password+ "'";User user = get(sql, User.class);if (user != null) {System.out.println("登陆成功!");} else {System.out.println("用户名或密码错误!");}}

数据库连接被用于向数据库服务器发送命令和 SQL 语句,并接受数据库服务器返回的结果,其实一个数据库连接就是一个Socket连接

🔎补充
SQL 注入利用某些系统没有对用户输入的数据进行充分的检查,而在用户输入数据中注入非法的 SQL 语句段或命令(如:SELECT user, password FROM user_table WHERE user=‘a’ OR 1 = ’ AND password = ’ OR ‘1’ = ‘1’) ,从而利用系统的 SQL 引擎完成恶意行为的做法


二、PreparedStatement

  • 可以调用 Connection 对象的 preparedStatement(String sql) 方法获取 PreparedStatement 对象
  • PreparedStatement 接口是 Statement 的子接口,它表示一条预编译过的 SQL 语句
  • PreparedStatement 对象所代表的 SQL 语句中的参数用问号(?)来表示
  • 调用 PreparedStatement 对象的 setXxx() 方法来设置这些参数. setXxx() 方法有两个参数,第一个参数是要设置的 SQL 语句中的参数的索引(从 1 开始),第二个是设置的 SQL 语句中的参数的值

🔥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

🔥使用PreparedStatement实现增、删、改操作

//通用的增、删、改操作(体现一:增、删、改 ; 体现二:针对于不同的表)public void update(String sql,Object ... args){Connection conn = null;PreparedStatement ps = null;try {//1.获取数据库的连接conn = JDBCUtils.getConnection();//2.获取PreparedStatement的实例 (或:预编译sql语句)ps = conn.prepareStatement(sql);//3.填充占位符for(int i = 0;i < args.length;i++){ps.setObject(i + 1, args[i]);}//4.执行sql语句ps.execute();} catch (Exception e) {e.printStackTrace();}finally{//5.关闭资源JDBCUtils.closeResource(conn, ps);}}

🔥使用PreparedStatement实现查询操作

// 通用的针对于不同表的查询:返回一个对象 (version 1.0)public <T> T getInstance(Class<T> clazz, String sql, Object... args) {Connection conn = null;PreparedStatement ps = null;ResultSet rs = null;try {// 1.获取数据库连接conn = JDBCUtils.getConnection();// 2.预编译sql语句,得到PreparedStatement对象ps = conn.prepareStatement(sql);// 3.填充占位符for (int i = 0; i < args.length; i++) {ps.setObject(i + 1, args[i]);}// 4.执行executeQuery(),得到结果集:ResultSetrs = ps.executeQuery();// 5.得到结果集的元数据:ResultSetMetaDataResultSetMetaData rsmd = rs.getMetaData();// 6.1通过ResultSetMetaData得到columnCount,columnLabel;通过ResultSet得到列值int columnCount = rsmd.getColumnCount();if (rs.next()) {T t = clazz.newInstance();for (int i = 0; i < columnCount; i++) {// 遍历每一个列// 获取列值Object columnVal = rs.getObject(i + 1);// 获取列的别名:列的别名,使用类的属性名充当String columnLabel = rsmd.getColumnLabel(i + 1);// 6.2使用反射,给对象的相应属性赋值Field field = clazz.getDeclaredField(columnLabel);field.setAccessible(true);field.set(t, columnVal);}return t;}} catch (Exception e) {e.printStackTrace();} finally {// 7.关闭资源JDBCUtils.closeResource(conn, ps, rs);}return null;}

三、ResultSet

查询需要调用PreparedStatement 的 executeQuery() 方法查询结果是一个ResultSet 对象,ResultSet 对象以逻辑表格的形式封装了执行数据库操作的结果集,ResultSet 接口由数据库厂商提供实现

ResultSet 返回的实际上就是一张数据表,有一个指针指向数据表的第一条记录的前面

ResultSet常用方法:
在这里插入图片描述
ResultSet 对象维护了一个指向当前数据行的游标,初始的时候,游标在第一行之前,可以通过 ResultSet 对象的 next() 方法移动到下一行。调用 next()方法检测下一行是否有效。若有效,该方法返回 true,且指针下移。相当于Iterator对象的 hasNext() 和 next() 方法的结合体,所以说ResultSet 返回的实际上就是一张数据表,有一个指针指向数据表的第一条记录的前面

🎁注意:Java与数据库交互涉及到的相关Java API中的索引都从1开始


🔥ResultSetMetaData

可用于获取关于 ResultSet 对象中列的类型和属性信息的对象

ResultSetMetaData meta = rs.getMetaData();

ResultSetMetaData常用方法:
在这里插入图片描述
从ResultSet到ResultSetMetaData的流程示意图:
<JDBC>使用PreparedStatement实现CRUD操作:你真的get到了吗?


四、资源的释放

释放ResultSet, Statement,Connection

可以在finally中关闭,保证及时其他代码出现异常,资源也一定能被关闭

数据库连接(Connection)是非常稀有的资源,用完后必须马上释放,如果Connection不能及时正确的关闭将导致系统宕机。Connection的使用原则是尽量晚创建,尽量早的释放


希望会对大家有所帮助嘻~ ,一起加油!