写在前面

虽然在实际开发中关于这些操作都不会让我们去写,但是掌握这代码的逻辑编写对我们使用框架有一定的帮助。
学习JDBC:请关注专栏——JDBC学习——内容详细
相关文章:
JDBC总述

JDBC连接Mysql数据(从简单到实用,超详细)
JDBC数据库事务
JDBC使用数据库连接池连接数据库(DBCP,C3P0,Druid)
Apache-DBUtils实现CRUD操作
欢迎光临我的主页:Java笔记本

PreparedStatement的使用

  • 1.PreparedStatement介绍
  • 2.使用PreparedStatement实现增、删、改操作
    • 主要步骤
    • 代码如下
  • 3.使用PreparedStatement实现查询操作
    • 主要步骤
    • 代码如下
  • 4.使用PreparedStatement操作BLOB类型字段
    • 向数据表中插入大数据类型
    • 修改数据表中的Blob类型字段
    • 从数据表中读取大数据类型
  • 5.批量插入
    • 高效的批量插入(案例)
      • 实现层次一:使用Statement
      • 实现层次二:使用PreparedStatement
      • 实现层次三
      • 实现层次四

要实现对数据库中数据的操作,首先要获取数据库的连接,关于连接,有做过详细总结:JDBC连接Mysql数据库
在 java.sql 包中有 3 个接口分别定义了对数据库的调用的不同方式:

  • Statement:用于执行静态 SQL 语句并返回它所生成结果的对象。
  • PrepatedStatement:SQL 语句被预编译并存储在此对象中,可以使用此对象多次高效地执行该语句。
  • CallableStatement:用于执行 SQL 存储过程
    由于Statement存在SQL注入问题,所以使用PreparedStatement实现CRUD操作

1.PreparedStatement介绍

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

JDBCUtils工具类

public class JDBCUtils {/*** @Description 获取数据库的连接*/public static Connection getConnection() throws Exception {// 1.读取配置文件中的4个基本信息InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("jdbc.properties");Properties pros = new Properties();pros.load(is);String user = pros.getProperty("user");String password = pros.getProperty("password");String url = pros.getProperty("url");String driverClass = pros.getProperty("driverClass");// 2.加载驱动Class.forName(driverClass);// 3.获取连接Connection conn = DriverManager.getConnection(url, user, password);return conn;}/*** * @Description 关闭连接和Statement的操作*/public static void closeResource(Connection conn,Statement ps){try {if(ps != null)ps.close();} catch (SQLException e) {e.printStackTrace();}try {if(conn != null)conn.close();} catch (SQLException e) {e.printStackTrace();}}/*** * @Description 关闭资源操作*/public static void closeResource(Connection conn,Statement ps,ResultSet rs){try {if(ps != null)ps.close();} catch (SQLException e) {e.printStackTrace();}try {if(conn != null)conn.close();} catch (SQLException e) {e.printStackTrace();}try {if(rs != null)rs.close();} catch (SQLException e) {e.printStackTrace();}}
}

2.使用PreparedStatement实现增、删、改操作

增删改可以总结出一个通用代码:
公共部分:

数据库连接,资源的关闭。
对于变动的:

sql语句:作为参数传入;
占位符:个数,不确定,可以通过可变形参,类型为Object;占位符的个数与可变形参的个数相同

填充占位符:使用循环;

主要步骤

1.获取数据库的连接
2.预编译sql语句
3.填充占位
4.执行
5.资源的关闭

代码如下

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);}}

3.使用PreparedStatement实现查询操作

查询操作会有结果集的返回;得专门处理结果集
一般将其封装为一个对象
针对于不同表的操作:

表也可以通过反射获取
sql语句,占位符;
查询的内容是可变的,可作为形参传入;
查询返回一个对象,返回值类型即为该对象的类型

主要步骤

1.获取数据库的连接
2.预编译sql语句,得到PreparedStatement对象
3.填充占位符
4.执行executeQuery(),得到结果集:ResultSet
5.得到结果集的元数据:ResultSetMetaData
6.通过ResultSetMetaData得到columnCount,columnLabel;通过ResultSet得到列值,使用反射,给对象的相应属性赋值
7.关闭资源

代码如下

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;}

细节注意:
当数据库的列名与类的属性名不一样时,可以给表的列名起别名为类的属性名
获取列的别名的方法:getColumLabel();


4.使用PreparedStatement操作BLOB类型字段

  • MySQL中,BLOB是一个二进制大型对象,是一个可以存储大量数据的容器,它能容纳不同大小的数据。
  • 插入BLOB类型的数据必须使用PreparedStatement,因为BLOB类型的数据无法使用字符串拼接写的。

向数据表中插入大数据类型

//获取连接
Connection conn = JDBCUtils.getConnection();String sql = "insert into customers(name,email,birth,photo)values(?,?,?,?)";
PreparedStatement ps = conn.prepareStatement(sql);// 填充占位符
ps.setString(1, "徐海强");
ps.setString(2, "xhq@126.com");
ps.setDate(3, new Date(new java.util.Date().getTime()));
// 操作Blob类型的变量
FileInputStream fis = new FileInputStream("xhq.png");
ps.setBlob(4, fis);
//执行
ps.execute();fis.close();
JDBCUtils.closeResource(conn, ps);

修改数据表中的Blob类型字段

Connection conn = JDBCUtils.getConnection();
String sql = "update customers set photo = ? where id = ?";
PreparedStatement ps = conn.prepareStatement(sql);// 填充占位符
// 操作Blob类型的变量
FileInputStream fis = new FileInputStream("coffee.png");
ps.setBlob(1, fis);
ps.setInt(2, 25);ps.execute();fis.close();
JDBCUtils.closeResource(conn, ps);

从数据表中读取大数据类型

String sql = "SELECT id, name, email, birth, photo FROM customer WHERE id = ?";
conn = getConnection();
ps = conn.prepareStatement(sql);
ps.setInt(1, 8);
rs = ps.executeQuery();
if(rs.next()){Integer id = rs.getInt(1);String name = rs.getString(2);String email = rs.getString(3);Date birth = rs.getDate(4);Customer cust = new Customer(id, name, email, birth);System.out.println(cust); //读取Blob类型的字段Blob photo = rs.getBlob(5);InputStream is = photo.getBinaryStream();OutputStream os = new FileOutputStream("c.jpg");byte [] buffer = new byte[1024];int len = 0;while((len = is.read(buffer)) != -1){os.write(buffer, 0, len);}JDBCUtils.closeResource(conn, ps, rs);if(is != null){is.close();}if(os !=  null){os.close();}}

5.批量插入

JDBC的批量处理语句包括下面三个方法:

  • addBatch(String):添加需要批量处理的SQL语句或是参数;
  • executeBatch():执行批量处理语句;
  • clearBatch():清空缓存的数据

通常我们会遇到两种批量执行SQL语句的情况:

  • 多条SQL语句的批量处理;
  • 一个SQL语句的批量传参;

高效的批量插入(案例)

举例:向数据表中插入20000条数据

  • 数据库中提供一个goods表。创建如下:
    CREATE TABLE goods(
    id INT PRIMARY KEY AUTO_INCREMENT,
    NAME VARCHAR(20)
    );

实现层次一:使用Statement

Connection conn = JDBCUtils.getConnection();
Statement st = conn.createStatement();
for(int i = 1;i <= 20000;i++){String sql = "insert into goods(name) values('name_' + "+ i +")";st.executeUpdate(sql);
}

实现层次二:使用PreparedStatement

Connection conn = JDBCUtils.getConnection();
String sql = "insert into goods(name)values(?)";
PreparedStatement ps = conn.prepareStatement(sql);
for(int i = 1;i <= 20000;i++){ps.setString(1, "name_" + i);ps.executeUpdate();
}
JDBCUtils.closeResource(conn, ps);

实现层次三

/** 修改1: 使用 addBatch() / executeBatch() / clearBatch()* 修改2:mysql服务器默认是关闭批处理的,我们需要通过一个参数,让mysql开启批处理的支持。*         ?rewriteBatchedStatements=true 写在配置文件的url后面* 修改3:使用更新的mysql 驱动:mysql-connector-java-5.1.37-bin.jar* */
@Test
public void testInsert1() throws Exception{Connection conn = JDBCUtils.getConnection();String sql = "insert into goods(name)values(?)";PreparedStatement ps = conn.prepareStatement(sql);for(int i = 1;i <= 1000000;i++){ps.setString(1, "name_" + i);//1.“攒”sqlps.addBatch();if(i % 500 == 0){//2.执行ps.executeBatch();//3.清空ps.clearBatch();}}JDBCUtils.closeResource(conn, ps);
}

实现层次四

/*
* 层次四:在层次三的基础上操作
* 使用Connection 的 setAutoCommit(false)  /  commit()
*/
@Test
public void testInsert2() throws Exception{Connection conn = JDBCUtils.getConnection();    //1.设置为不自动提交数据conn.setAutoCommit(false);    String sql = "insert into goods(name)values(?)";PreparedStatement ps = conn.prepareStatement(sql);for(int i = 1;i <= 1000000;i++){ps.setString(1, "name_" + i);   //1.“攒”sqlps.addBatch();if(i % 500 == 0){//2.执行ps.executeBatch();//3.清空ps.clearBatch();}}//2.提交数据conn.commit();   JDBCUtils.closeResource(conn, ps);
}

JDBC完成对数据库数据操作(增,删,改,查)相关推荐

  1. 表单的增 删 改 查

    django单表操作 增 删 改 查 一.实现:增.删.改.查 1.获取所有数据显示在页面上 model.Classes.object.all(),拿到数据后,渲染给前端;前端通过for循环的方式,取 ...

  2. properties(map)增.删.改.查.遍历

    import java.util.Map; import java.util.Properties; import java.util.Set;/*** properties(map)增.删.改.查. ...

  3. python学生姓名添加删除_python-函数-实现学生管理系统,完成对学员的增,删,改,查和退出学生管理系统。...

    实现学生管理系统,完成对学员的增,删,改,查和退出学生管理系统. 要求1:使用一个list用于保存学生的姓名. 要求2:输入0显示所有学员信息,1代表增加,2代表删除,3代表修改,4代表查询,exit ...

  4. Linux技术--mysql数据库增-删-改-查

    # mysql 数据库 ## 数据库的操作 ### 五个单位 * 数据库服务器   Linux或者 windows  * 数据库  * 数据表 * 数据字段 * 数据行 ### 连接数据库 ``` 1 ...

  5. PySpark︱DataFrame操作指南:增/删/改/查/合并/统计与数据处理

    笔者最近需要使用pyspark进行数据整理,于是乎给自己整理一份使用指南.pyspark.dataframe跟pandas的差别还是挺大的. 文章目录 1.-------- 查 -------- -- ...

  6. 简单的php数据库操作类代码(增,删,改,查)

    数据库操纵基本流程为: 1.连接数据库服务器 2.选择数据库 3.执行SQL语句 4.处理结果集 5.打印操作信息 其中用到的相关函数有 •resource mysql_connect ( [stri ...

  7. 【django】数据库操作-增 删 改

    一.增加数据 增加数据有两种⽅法. 1)save 通过创建模型类对象,执⾏对象的save()⽅法保存到数据库中. f1=FilmInfo(fname='我爱你中国',pub_data='2021-10 ...

  8. Python 操作 Elasticsearch 实现 增 删 改 查

    Github 地址:https://github.com/elastic/elasticsearch-py/blob/master/docs/index.rst 官网地址:https://elasti ...

  9. python_操作MySQL 初解 之__类方法调用并 增-删-改-查

    文件一: 调用(sqls文件) 1 # 导入模块 2 import pymysql 3 from sqls import * 4 # 创建类 5 class KaoShi(object): 6 7 # ...

最新文章

  1. 判断图有无环_链表:环找到了,那入口呢?
  2. 【实习项目记录】(一)加密算法MD5和RSA
  3. python编写异常处理_Python 简明教程 --- 23,Python 异常处理
  4. Visual Event插件----查看html元素绑定的事件与方法的利器
  5. python下载的库要放到哪里-Python下载url并保存文件的三种方法
  6. 数据结构实验之查找六:顺序查找
  7. 看完这篇你就明白,为什么说大部分企业建设数据中台都会失败?
  8. c语言做最小公倍数,C语言用两种实现最小公倍数
  9. Varnish的相关知识,varnish的简单应用
  10. C++ 工具类 —— 词条类(Entry)
  11. tp框架like模糊查询报错
  12. 讯飞离线语音合成(语记)
  13. 模线性方程ax≡b(mod n) (再结合 程序理解)
  14. 前端Vue页面加水印方法(带源码)
  15. Android编译打包报错Invalid keystore format
  16. 中心透视投影和鱼眼投影的区别(Central perspective projection vs. fisheye projection)
  17. 曼哈特软件助力葡萄酒分销商14 Degrees实现业务增长
  18. 简单python爬取微博并写入excel
  19. AutoDock安装及AutoDockTools闪退问题
  20. 面试复习题--音视频

热门文章

  1. 最新最全论文合集——FOCS 历年最佳论文汇总
  2. 【云计算】通俗易懂讲云计算与虚拟化区别
  3. 用matlab计算雅可比矩阵
  4. [附源码]Java计算机毕业设计SSM爱宝贝影楼管理系统
  5. android修改默认遥控器键值,android 中遥控器键值的添加和修改
  6. burpsuite抓取手机app数据包(通过笔记本开热点方式)
  7. UnicodeEncodeError: ‘latin-1‘ codec can‘t encode characters in position
  8. 数学建模模型6——Kmeans算法【数据型】
  9. Springboot 报错 template might not exist or might not be accessible by any of the configured Template
  10. 51kantv是什么?桌面上总是出现51kantv,怎么办?