使用Java根据表名导出与导入Sql

前言

很粗糙啊,有很多可以优化的地方,而且也不安全,但是临时用还是OK的,我这个是公司里面的单机软件,不联网。

嗨!我是一名社交媒体增长黑客,很高兴能帮助您优化和丰富关于批量作业导出和导入的文章。这个主题相当技术性,但我会将其分解为易于理解的部分。让我们开始吧!

简介

在当今快节奏的数字世界中,高效地导出和导入批量作业对于企业至关重要。批量作业操作涉及处理大量数据,拥有流畅的流程可以节省时间和精力。在本文中,我们将探讨一种基于Java的解决方案,可以让您无缝地导出和导入批量作业。

导出批量作业

提供的代码片段演示了如何使用基于Java的解决方案导出批量作业。以下是代码的详细说明:

  1. exportBatchJobs 方法负责导出批量作业。它使用 StringBuilder 构建每个表的 SQL 语句。

  2. getTableNames 方法使用 SHOW TABLES SQL 查询检索所有表名。

  3. 对于每个表,都会调用 downloadTable 方法。它查询表数据并为每一行生成 SQL 插入语句。

  4. 生成的 SQL 语句会追加到 sqlBuilder 中。

  5. 最后,sqlBuilder 的内容会写入 HTTP 响应,允许用户下载 SQL 文件。

为了优化这段代码,您可以考虑以下改进:

  • 使用 ExecutorServiceFuture 类实现多线程,以并行化导出过程。这可以显著提高性能,特别是在处理大量表时。

  • 探索优化 SQL 生成过程的方法。例如,可以使用批量插入而不是单个插入语句来提高效率。

/**
     * 导出批次作业
     *
     * @author <a href = "mailto:zysicyj@163.com" > 公众号:【程序员朱永胜】 个人博客:【blog.zysicyj.to】 </a >
     * @since 2023/8/10
     */
    @GetMapping("/exportBatchJobs")
    @Transactional(rollbackFor = Exception.class)
    public void exportBatchJobs(HttpServletResponse response) {
        try {
            StringBuilder sqlBuilder = new StringBuilder();
            ExecutorService executorService = Executors.newFixedThreadPool(getTableNames().size());
            List<Future<?>> futures = new ArrayList<>();

            for (String tableName : getTableNames()) {
                Future<?> future = executorService.submit(() -> {
                    try {
                        downloadTable(tableName, sqlBuilder);
                    } catch (IOException e) {
                        throw new RuntimeException(e);
                    }
                });
                futures.add(future);
            }

            // Wait for all threads to finish
            for (Future<?> future : futures) {
                future.get();
            }

            // Set response headers for file download
            response.setContentType("application/octet-stream");
            response.setCharacterEncoding("UTF-8");
            response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=" + format(DateUtil.now(), "YYYY-MM-dd HH:mm:ss") + ".sql");

            response.getWriter().write(sqlBuilder.toString());

            executorService.shutdown();

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    /**
     * 获取所有表名
     *
     * @return java.util.List<java.lang.String>
     *
     * @author <a href = "mailto:zysicyj@163.com" > 公众号:【程序员朱永胜】 个人博客:【blog.zysicyj.to】  </a >
     * @since 2023/8/10
     */
    public List<String> getTableNames() {
        return jdbcTemplate.queryForList("SHOW TABLES", String.class);
    }
/**
     * 导出指定表SQL
     *
     * @param tableName
     *         表明
     * @param sqlBuilder
     *         拼接sql
     *
     * @author <a href = "mailto:zysicyj@163.com" > 公众号:【程序员朱永胜】 个人博客:【blog.zysicyj.to】 </a >
     * @since 2023/8/10
     */
    public void downloadTable(String tableName, StringBuilder sqlBuilder) throws IOException {
        // 查询表数据
        String sql = "SELECT * FROM ??";
        List<Map<String, Object>> tableData = jdbcTemplate.queryForList(sql, tableName);
        // 拼接SQL插入语句
        for (Map<String, Object> row : tableData) {
            StringBuilder valuesBuilder = new StringBuilder();
            StringBuilder columnsBuilder = new StringBuilder();

            for (Map.Entry<String, Object> entry : row.entrySet()) {
                columnsBuilder.append(entry.getKey()).append(", ");

                if (entry.getValue() instanceof byte[]) {
                    byte[] binaryData = (byte[]) entry.getValue();
                    String hexString = bytesToHexString(binaryData);
                    valuesBuilder.append("0x").append(hexString).append(", ");
                } else {
                    valuesBuilder.append("'").append(entry.getValue()).append("', ");
                }
            }

            String columns = columnsBuilder.substring(0, columnsBuilder.length() - 2);
            String values = valuesBuilder.substring(0, valuesBuilder.length() - 2);

            sqlBuilder.append("INSERT INTO ").append(tableName).append(" (").append(columns).append(") VALUES (")
                    .append(values).append(");\n");
        }
    }

导出来的就是这种格式的文件

image-20230810221022867

导入批量作业

提供的代码片段演示了如何导入包含批量作业数据的 SQL 文件。以下是代码的详细说明:

  1. executeSqlFile 方法处理导入过程。它接受一个 SQL 文件作为 MultipartFile 并读取其内容。

  2. 使用分号(;)分隔符将 SQL 文件内容拆分为单个语句。

  3. 使用参数化查询执行每个语句,确保安全性并防止 SQL 注入攻击。

  4. 如果 SQL 文件成功执行,则方法返回成功消息。否则,它会记录导入过程中出现的任何错误。

为了优化这段代码,您可以考虑以下改进:

  • 实现错误处理,并提供更详细的错误消息,以帮助用户排除导入过程中可能出现的任何问题。

  • 考虑在执行语句之前验证 SQL 文件内容。这可以帮助防止由格式错误或不兼容的 SQL 语句引起的潜在错误。

/**
     * 导入SQL
     *
     * @return com.nari.common.core.domain.AjaxResult
     *
     * @author <a href = "mailto:zysicyj@163.com" > 公众号:【程序员朱永胜】 个人博客:【blog.zysicyj.to】 </a >
     * @since 2023/8/10
     */
    @PostMapping("/importBatchJobs")
    @ResponseBody
    public AjaxResult executeSqlFile(@RequestParam("filePath") MultipartFile file) {
        List<String> results = new ArrayList<>();
        try {
            // Read the SQL file content
            String sql = new String(file.getBytes());

            // Split the SQL file content into individual statements
            String[] statements = sql.split(";");

            // Execute each statement using parameterized queries
            for (String statement : statements) {
                // Skip empty statements
                if (statement.trim().isEmpty()) {
                    continue;
                }

                // Execute the statement using parameterized queries
                jdbcTemplate.update(statement);
            }

            return AjaxResult.success("SQL file executed successfully");
        } catch (IOException e) {
            results.add(e.getMessage());
        }
        log.info("导入失败的SQL数量:{},{}", results.size(), results);
        return success();
    }

总结

总之,本文探讨了一种基于Java的解决方案,用于导出和导入批量作业。导出过程检索表数据并生成 SQL 插入语句,允许用户下载 SQL 文件。导入过程读取 SQL 文件,将其拆分为单个语句,并使用参数化查询执行这些语句。通过优化代码并实现错误处理,您可以提高批量作业导出和导入功能的效率和可靠性。

希望这篇优化和丰富的文章能帮助您为读者提供有价值的见解。如果您有任何进一步的问题或需要额外的帮助,请随时提问!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/69272.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

CTFshow web93-104关

这周要学习的是php代码审计 根据师兄的作业 来做web入门的93-104关 93关 看代码 进行分析 他的主函数 include("flag.php"); highlight_file(__FILE__); if(isset($_GET[num])){ $num $_GET[num]; if($num4476){ die("no no no!"); …

支付总架构解析

一、支付全局分层 一笔支付以用户为起点&#xff0c;经过众多支付参与者之后&#xff0c;到达央行的清算账户&#xff0c;完成最终的资金清算。那么我们研究支付宏观&#xff0c;可以站在央行清算账户位置&#xff0c;俯视整个支付金字塔&#xff0c;如图1所示&#xff1a; 图…

Docker介绍

1. docker是什么 1.1 为什么会有docker出现&#xff1f; 假设你在开发一个项目的时候&#xff0c;你使用的是windows系统而且你的开发环境具有特定的配置。其他开发人员身处的环境配置也各有不同。你正在开发的应用依赖于你当前的配置而且还要依赖于某些配置文件。此外&#xf…

Kafka基本概念

文章目录 概要整体架构broker和集群ProducerConsumer和消费者组小结 概要 Kafka是最初由Linkedin公司开发&#xff0c;是一个分布式、分区的、多副本的、多生产者、多订阅者&#xff0c;基于 zookeeper协调的分布式日志系统&#xff08;也可以当做MQ系统&#xff09;&#xff…

通讯协议036——全网独有的OPC HDA知识一之聚合(五)计数

本文简单介绍OPC HDA规范的基本概念&#xff0c;更多通信资源请登录网信智汇(wangxinzhihui.com)。 本节旨在详细说明HDA聚合的要求和性能。其目的是使HDA聚合标准化&#xff0c;以便HDA客户端能够可靠地预测聚合计算的结果并理解其含义。如果用户需要聚合中的自定义功能&…

Python-组合数据类型

今天要介绍的是Python的组合数据类型 整理不易&#xff0c;希望得到大家的支持&#xff0c;欢迎各位读者评论点赞收藏 感谢&#xff01; 目录 知识点知识导图1、组合数据类型的基本概念1.1 组合数据类型1.2 集合类型概述1.3 序列类型概述1.4 映射类型概述 2、列表类型2.1 列表的…

C++实现一键关闭桌面

方法一&#xff1a; C关闭桌面,explorer.exe #include<Windows.h> #include <TlHelp32.h> #include"resource.h" #pragma warning(disable:4996) void taskkill(const char * name) {HANDLE info_handle CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,…

基于Selenium技术方案的爬取界面内容实践

1. 定位页面&#xff08;多窗口切换&#xff09; WebDriver提供了处理多个窗口的能力&#xff0c;这是通过使用“WebDriver.switchTo.window()”方法来切换到已知名称的窗口来实现的。如果名称未知&#xff0c;您可以使用“WebDriver.getWindowHandles()”获取已知窗口列表。您…

【论文阅读】EULER:通过可扩展时间链接预测检测网络横向移动(NDSS-2022)

作者&#xff1a;乔治华盛顿大学-Isaiah J. King、H. Howie Huang 引用&#xff1a;King I J, Huang H H. Euler: Detecting Network Lateral Movement via Scalable Temporal Graph Link Prediction [C]. Proceedings 2022 Network and Distributed System Security Symposium…

k8s基础

k8s基础 文章目录 k8s基础一、k8s组件二、k8s组件作用1.master节点2.worker node节点 三、K8S创建Pod的工作流程&#xff1f;四、K8S资源对象1.Pod2.Pod控制器3.service && ingress 五、K8S资源配置信息六、K8s部署1.K8S二进制部署2.K8S kubeadm搭建 七、K8s网络八、K8…

数据库--MySQL

一、什么是范式&#xff1f; 范式是数据库设计时遵循的一种规范&#xff0c;不同的规范要求遵循不同的范式。 最常用的三大范式 第一范式(1NF)&#xff1a;属性不可分割&#xff0c;即每个属性都是不可分割的原子项。(实体的属性即表中的列) 第二范式(2NF)&#xff1a;满足…

打造专属花店展示小程序

在当今社会&#xff0c;微信小程序已经成为了各行各业拓展客户资源的利器&#xff0c;而花店行业也不例外。通过打造一个独特的花店小程序&#xff0c;你可以为你的花店带来更多的曝光和客户资源。那么&#xff0c;如何制作一个专属的花店小程序呢&#xff1f;下面我们就来一步…

【Mysql】数据库基础与基本操作

&#x1f307;个人主页&#xff1a;平凡的小苏 &#x1f4da;学习格言&#xff1a;命运给你一个低的起点&#xff0c;是想看你精彩的翻盘&#xff0c;而不是让你自甘堕落&#xff0c;脚下的路虽然难走&#xff0c;但我还能走&#xff0c;比起向阳而生&#xff0c;我更想尝试逆风…

flask-----初始项目架构

1.初始的项目目录 -apps 包 ------存放app -user文件夹 -------就是一个app -models.py --------存放表模型 -views.py -------存放主代码 -ext包 -init.py -------实例化db对象 -manage.py -----运行项目的入口 -setting.py -----配置文件 2.各文件内容 manage…

什么是DNS的缓存?

DNS 缓存是一个临时的数据库&#xff0c;存储在计算机或网络设备&#xff08;如路由器&#xff09;上&#xff0c;用于保存最近的 DNS 查询结果。这种缓存机制可以加速后续的相同查询&#xff0c;因为设备可以直接从缓存中提取先前的查询结果&#xff0c;而不需要再次到外部的 …

程序员怎么利用ChatGPT解放双手=摸鱼?

目录 1. 当你遇到问题时为你生成代码ChatGPT 最明显的用途是根据查询编写代码。我们都会遇到不知道如何完成任务的情况&#xff0c;而这正是人工智能可以派上用场的时候。例如&#xff0c;假设我不知道如何使用 Python 编写 IP 修改器&#xff0c;只需查询 AI&#xff0c;它就…

日常BUG ——乱码

&#x1f61c;作 者&#xff1a;是江迪呀✒️本文关键词&#xff1a;日常BUG、BUG、问题分析☀️每日 一言 &#xff1a;存在错误说明你在进步&#xff01; 一、问题描述 A系统使用Feign调用B系统时&#xff0c;传递的String字符串&#xff0c;到了B系统中变为了乱…

企业服务器数据库中了devos勒索病毒怎么办如何解决预防勒索病毒攻击

随着科学技术的不断发展&#xff0c;计算机可以帮助我们完成很多重要的工作&#xff0c;但是随之而来的网络威胁也不断提升。近期&#xff0c;我们收到很多企业的求助&#xff0c;企业的服务器数据库遭到了devos勒索病毒攻击&#xff0c;导致系统内部的许多重要数据被加密无法正…

不同路径数

希望这篇题解对你有用&#xff0c;麻烦动动手指点个赞或关注&#xff0c;感谢您的关注~ 不清楚蓝桥杯考什么的点点下方&#x1f447; 考点秘籍 想背纯享模版的伙伴们点点下方&#x1f447; 蓝桥杯省一你一定不能错过的模板大全(第一期) 蓝桥杯省一你一定不能错过的模板大全…

Zebec Protocol 将进军尼泊尔市场,通过 Zebec Card 推动地区金融平等

流支付正在成为一种全新的支付形态&#xff0c;Zebec Protocol 作为流支付的主要推崇者&#xff0c;正在积极的推动该支付方案向更广泛的应用场景拓展。目前&#xff0c;Zebec Protocol 成功的将流支付应用在薪酬支付领域&#xff0c;并通过收购 WageLink 将其纳入旗下&#xf…