JDBC实现数据库批量插入

2023-09-22 08:30:00

目录

一、JDBC实现批量插入几种方式

二、PreparedStatement addBatch方法使用

三、Statement 和PreparedStatement 区别 


使用Java数据库连接(JDBC)实现批量插入可以提高数据库操作的效率,特别是在需要一次性插入多条数据时。

一、JDBC实现批量插入几种方式

  • 使用PreparedStatement的批处理: 这是最常见的批量插入方式之一,适用于大多数数据库。你可以使用addBatch方法将多个插入语句添加到PreparedStatement对象中,然后使用executeBatch执行批处理操作。这个方式在上一个回答中已经进行了详细说明。

  • 使用批处理语句: 一些数据库支持批处理语句,例如MySQL的INSERT INTO ... VALUES (?, ?), (?, ?), ...语法。你可以构建这样的SQL语句,一次性插入多个数据行。

String sql = "INSERT INTO your_table (column1, column2) VALUES (?, ?), (?, ?), (?, ?)";
PreparedStatement preparedStatement = connection.prepareStatement(sql);

// 设置占位符的值
preparedStatement.setString(1, value1);
preparedStatement.setString(2, value2);
preparedStatement.setString(3, value3);
preparedStatement.setString(4, value4);
preparedStatement.setString(5, value5);
preparedStatement.setString(6, value6);

// 执行批处理
int[] batchResults = preparedStatement.executeBatch();
  •  使用JDBC批处理API: JDBC 2.0引入了java.sql.Statement接口的批处理方法。你可以使用addBatch方法将多个SQL语句添加到Statement对象中,然后使用executeBatch方法执行批处理操作。
Statement statement = connection.createStatement();
statement.addBatch("INSERT INTO your_table (column1, column2) VALUES ('value1', 'value2')");
statement.addBatch("INSERT INTO your_table (column1, column2) VALUES ('value3', 'value4')");
statement.addBatch("INSERT INTO your_table (column1, column2) VALUES ('value5', 'value6')");

int[] batchResults = statement.executeBatch();

二、PreparedStatement addBatch方法使用

PreparedStatementaddBatch方法用于将多个SQL语句添加到批处理中,以便一次性执行多个SQL操作。这可以显著提高数据库操作的性能,尤其是在需要插入、更新或删除多个数据行时。 

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;

public class BatchInsertExample {

    public static void main(String[] args) {
        String jdbcUrl = "jdbc:mysql://localhost:3306/tbl";
        String username = "root";
        String password = "root";

        Connection connection = null;
        PreparedStatement preparedStatement = null;

        try {
            // 建立数据库连接
            connection = DriverManager.getConnection(jdbcUrl, username, password);

            // SQL插入语句,使用占位符来防止SQL注入
            String sql = "INSERT INTO goods(name, price) VALUES (?, ?)";

            // 创建PreparedStatement对象,并设置为批处理模式
            preparedStatement = connection.prepareStatement(sql);
            connection.setAutoCommit(false); // 设置为手动提交

            // 循环添加多个批处理操作
            for (int i = 0; i < 10; i++) {
                // 设置占位符的值
                preparedStatement.setString(1, "value" + i);
                preparedStatement.setString(2, "value" + (i * 2));

                // 添加到批处理中
                preparedStatement.addBatch();
            }

            // 执行批处理
            int[] batchResults = preparedStatement.executeBatch();

            // 手动提交事务
            connection.commit();

            // 检查批处理执行结果
            for (int result : batchResults) {
                if (result == PreparedStatement.SUCCESS_NO_INFO || result == PreparedStatement.EXECUTE_FAILED) {
                    // 处理失败的情况
                }
            }

        } catch (SQLException e) {
            e.printStackTrace();
            try {
                // 发生异常时回滚事务
                if (connection != null) {
                    connection.rollback();
                }
            } catch (SQLException ex) {
                ex.printStackTrace();
            }
        } finally {
            try {
                // 关闭PreparedStatement和Connection
                if (preparedStatement != null) {
                    preparedStatement.close();
                }
                if (connection != null) {
                    connection.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

在上述示例中,我们创建了一个PreparedStatement对象,将多个插入操作添加到批处理中,并最后执行批处理。注意以下几点:

  1. 使用setString等方法设置占位符的值,然后使用addBatch方法将每个操作添加到批处理中。
  2. 执行批处理操作后,executeBatch返回一个整数数组,其中包含每个批处理操作的执行结果。你可以根据需要处理失败的情况。
  3. 为了保持数据的一致性,我们使用connection.setAutoCommit(false)关闭了自动提交模式,手动提交事务,以便在所有操作成功后一起提交。
  4. 在异常情况下,我们使用connection.rollback()回滚事务,以避免数据不一致。

connection.setAutoCommit是用于设置JDBC连接的自动提交模式的方法。在JDBC中,自动提交是指每个SQL操作是否都立即提交到数据库,或者是否需要手动调用commit方法来提交事务。

默认情况下,JDBC连接的自动提交模式是打开的(true)。这意味着每个SQL操作都会立即提交到数据库,形成一个独立的事务。这对于简单的操作非常方便,但在某些情况下,你可能希望将多个SQL操作组合成一个事务以确保数据的一致性。

你可以使用connection.setAutoCommit(false)来关闭自动提交模式,这样就可以手动管理事务。一旦关闭了自动提交,你可以通过调用connection.commit()来提交事务,将之前的SQL操作组合成一个事务。

三、Statement 和PreparedStatement 区别 

StatementPreparedStatement是Java JDBC(Java数据库连接)中两种执行SQL语句的方式,它们在使用和性能上有一些重要的区别。

Statement:

  1. 静态SQL语句: Statement用于执行静态SQL语句,这意味着SQL查询在编写代码时已经被定义好,不能包含动态参数。

  2. 不安全: 由于Statement不支持参数化查询,因此它容易受到SQL注入攻击。如果直接将用户提供的数据拼接到SQL语句中,可能会导致安全问题。

  3. 性能问题: 在需要多次执行相同的SQL语句时,Statement的性能通常较差。每次执行时,数据库都需要解析和编译SQL语句。

  4. 代码可读性: 由于SQL语句直接嵌入在Java代码中,Statement的代码通常比较难读懂,维护困难。

PreparedStatement:

  1. 动态SQL语句: PreparedStatement用于执行动态SQL语句,它支持参数化查询。你可以使用占位符来表示参数,然后在执行之前设置这些参数的值。这使得你可以轻松地构建动态查询,根据不同的输入执行不同的查询。

  2. 安全性: 由于参数化查询,PreparedStatement可以防止SQL注入攻击,因为参数值不会直接嵌入到SQL语句中,而是通过参数传递。

  3. 性能优化: PreparedStatement通常比Statement更高效,因为数据库可以缓存已编译的SQL语句,而且每次只需传递参数值,而不是重新解析和编译SQL语句。

  4. 代码可读性: 使用PreparedStatement可以使代码更清晰和易于维护,因为SQL语句与参数值分离,降低了代码的复杂性。

综上所述,如果你需要执行动态SQL查询、提高安全性和性能,通常建议使用PreparedStatementStatement适用于那些不需要参数化查询,只需要执行静态SQL语句的情况。 

更多推荐

来自华为的暴击?传高通裁员赔偿N+7 | 百能云芯

自9月20日起,高通裁员的新闻在网络上持续发酵。尽管市场充满了关于裁员细节的传言,但截至目前,高通官方尚未对此发表评论。消息称,高通此次裁员的“重灾区”在上海的无线研发部门,甚至有传言称将直接关闭上海研发中心。裁员的补偿标准也备受关注,根据不同情况,高通将提供不同的补偿标准。多位网友在社交媒体上爆料称,高通上海研发部门

个人博客搭建记录

个人博客地址:www.jiasun.top使用githubpage+hexo搭建,主题为fluid,搭建步骤参照:Github+hexo实现自己的个人博客、配置主题(超详细)主题:https://hexo.fluid-dev.com/搭建时的问题:1Ubuntuapt默认下载的nodejs版本过低,snap安装18.1

抖音seo矩阵系统源代码开发技术文档分享--SaaS开源

抖音SEO矩阵系统源代码开发文档可能包括以下内容:系统架构设计系统架构概述:包括系统的组成部分、技术框架和设计思路等。数据库设计:说明数据库的结构、表的关联和数据类型等。API接口设计:定义系统的API接口、请求参数和返回结果等。前端开发指南前端框架选型:选择合适的前端框架和组件库等。UI设计规范:制定界面的布局、样式

element日历插件获取显示的第一天和最后一天

和重置日期内容显示需求是要传入当前显示的第一天和最后一天来获取范围,再判断某个日期是否有内容标记已知星期排版是固定的,第一天是星期天,最后一天是星期六。通过当月1号和最后一天再往前推算需要展示上个月几天,和下个月几天。//获取日历显示时间范围constgetRange=(date)=>{//日历第一天letfirstD

前端JavaScript设计模式探秘:理论与实践

前端JavaScript设计模式探秘:理论与实践在前端开发领域,JavaScript设计模式是一种重要的软件开发方法,可以帮助开发者解决常见的Web界面开发问题,提高代码的可维护性、可扩展性和可重用性。本文将详细探讨JavaScript设计模式的基本概念、常见类型以及应用场景,并通过实际案例展示模式的实现细节和代码示例

ES9,ES10

文章目录ES9新特性对象的剩余参数与扩展运算符正则表达式命名捕获组Promise.finally()异步遍历器ES10新特性Object.fromEntriestrimStart()andtrimEnd()Symbol对象的description属性可选的catchES9新特性对象的剩余参数与扩展运算符对象的剩余参数l

使用node实现websocket

使用node实现websocket什么是websocketwebsocket代表了Web应用程序通信方式的根本转变。不同于传统的HTTP请求响应周期,即客户端从服务器请求数据并等待响应,websocket在客户端和服务器之间建立一个持久的全双工连接。这意味着一旦建立了websocket,数据可以在任何时候双向流动,而不

各种存储性能瓶颈如何分析与优化?

【摘要】本文结合实践剖析存储系统的架构及运行原理,深入分析各种存储性能瓶颈场景,并提出相应的性能优化手段,希望对同行有一定的借鉴和参考价值。【作者】陈萍春,现就职于保险行业,拥有多年的系统、存储以及数据备份等运维工作经验。前言可靠性、安全性和性能是IT系统最重要的三个评价维度。对于IT系统来说,可靠性和安全性是基础,系

如何使用 NestJS 构建 GraphQL API

本GraphQL和NestJS教程最后更新于2023年8月,旨在探索使用GraphQLAPI的好处。NestJS是一个TypeScriptNode.js框架,可帮助您构建企业级,高效且可扩展的Node.js应用程序。它支持RESTful和GraphQLAPI设计方法。GraphQL是一种用于API的查询语言,也是使用现

华为认证 | 安全HCIP和数通HCIP,该怎么选?

华为认证是全球认可的IT行业技术认证,是IT人员提升职业技能和市场竞争力的重要途径。为了满足不同网络工程师的职业需求和市场需求,华为认证设置了多个不同的认证方向,华为安全HCIP和数通HCIP都是华为认证中的一种。那么,这两个认证应该如何选择呢?01学华为安全HCIP能获得什么HCIP-Security培训与认证具备大

网络基础-传输层协议-TCP/UDP

TCP/UDP谈一谈端口号为什么会有端口号端口号划分一个进程可以bind多个端口号吗一个端口号可以被多个进程bind吗UDP协议格式udp协议的特点无连接不可靠面向数据报UDP缓冲区TCP协议格式![在这里插入图片描述](https://img-blog.csdnimg.cn/35e43cc2575c4188999fe

热文推荐