文档章节

一个用Java语言写的生成SQL(merge)脚本的小工具

北风其凉
 北风其凉
发布于 2016/02/17 00:13
字数 1566
阅读 755
收藏 9
点赞 1
评论 0

一、工具的制作背景

最近在工作中遇到了这样一个问题:前台的客户端程序需要在后台指定程序更新后清空本地的缓存,后台程序的数量不止一个。这个问题的症结在于客户端程序并不知道后台程序是什么时候更新的,为了解决这个问题,我想了如下的办法:

1、在配置表中设立配置项,保存后台程序的版本号,每次后台程序更新时,将这个版本号也同步更新

2、前台客户端程序也保存一组后台程序的版本号,每次登录程序后读取配置表中的版本号,二者进行比较,如果有一组版本号不匹配,则说明后台程序有变动,前台客户端就需要清空本地的缓存数据了

本次制作的小工具,功能就是在上面的第1步时,根据XML的配置生成若干个SQL语句(merge语句),用于更新配置表中的对应配置项。设计这个工具的目的,一是在修改SQL语句的时候可以避免因马虎等因素造成的语句书写错误,二是同时生成一次语句后可以分享给多个人在多个环境上同时进行升级。

二、工具代码

这个小工具是用Java语言写的,工程如下:

文件version.xml存储了我们准备配置的版本号信息

<?xml version="1.0" encoding="UTF-8"?>
<systems author="Tsybius2014" output="updateVer.sql" remark="none">
  <!-- 系统1 -->
  <system config_no="110020" name="System1" version="v1.2.0.1" enabled="true" />
  <!-- 系统2 -->
  <system config_no="110021" name="System2" version="v1.2.3.4" enabled="true" />
  <!-- 系统3 -->
  <system config_no="110022" name="System3" version="v1.0.0.1" enabled="false" />
</systems>

各配置项说明如下:

1、output为输出的sql文件路径

2、author为作者信息、remark为备注信息,这两个信息会出现在生出的sql脚本的首部,以注释形式出现

3、每个system节点配置了一个系统,config_no为配置项编号,name为配置项说明,version为该系统的版本号,enabled为程序执行时是否生成该系统的MergeInto语句

要将version.xml的内容生成为MergeInto语句,还需要一个模板,我将它放在文件template.txt中,内容如下:

MERGE INTO INTERINS.SYS_CONFIG CONFIG
USING (SELECT #{config_no} AS CONFIG_NO,
              '11' AS SUB_SYS_CODE,
              #{name} AS CONFIG_NAME,
              '0' AS MANAGE_LEVEL,
              '0' AS ACCESS_LEVEL,
              '2' AS DATA_TYPE,
              #{version} AS STR_CONFIG,
              '1' AS CONFIG_STATUS,
              TO_CHAR(SYSDATE,'yyyy-MM-dd HH:mm:ss') AS DATETIME
       FROM   DUAL) INPUT
ON (CONFIG.CONFIG_NO = INPUT.CONFIG_NO)
WHEN MATCHED THEN
  UPDATE
  SET    CONFIG.SUB_SYS_CODE  = INPUT.SUB_SYS_CODE,
         CONFIG.CONFIG_NAME   = INPUT.CONFIG_NAME,
         CONFIG.DATA_TYPE     = INPUT.DATA_TYPE,
         CONFIG.STR_CONFIG    = INPUT.STR_CONFIG,
         CONFIG.CONFIG_STATUS = INPUT.CONFIG_STATUS,
         CONFIG.REMARK        = 'UPDATE BY GEN_MERGE_INTOS ON ' || INPUT.DATETIME
WHEN NOT MATCHED THEN
  INSERT
    (CONFIG_NO,
     SUB_SYS_CODE,
     CONFIG_NAME,
     MANAGE_LEVEL,
     ACCESS_LEVEL,
     DATA_TYPE,
     STR_CONFIG,
     CONFIG_STATUS,
     REMARK)
  VALUES
    (INPUT.CONFIG_NO,
     INPUT.SUB_SYS_CODE,
     INPUT.CONFIG_NAME,
     INPUT.MANAGE_LEVEL,
     INPUT.ACCESS_LEVEL,
     INPUT.DATA_TYPE,
     INPUT.STR_CONFIG,
     INPUT.CONFIG_STATUS,
     'INSERT BY GEN_MERGE_INTOS ON ' || INPUT.DATETIME);

其中,用config_no替换#{config_no},用name替换#{name},用version替换#{version},就可以生成对应的MergeInto语句了。

GenMergeIntos.java代码如下:

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.LinkedList;
import java.util.Queue;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

/**
 * SQL脚本生成工具 - 用于系统版本升级后刷新缓存
 * 
 * @文件名称 GenMergeIntos.java
 * @文件作者 Tsybius2014
 * @创建时间 2016年2月15日 上午11:01:51
 */
public class GenMergeIntos {

    // 输出文件地址(需从配置文件中读取)
    static String outputPath = "";
    // 输出文件作者(需从配置文件中读取)
    static String author = "";
    // 备注信息(需从配置文件中读取)
    static String remark = "";
    // 配置文件地址 - 调试时请修改为 src\\version.xml
    static String configPath = "version.xml";
    // 模板文件地址 - 调试时请修改为 src\\template.xml
    static String templatePath = "template.txt";
    // 生成的SQL语句暂存于此
    static Queue<String> mergeIntos = null;

    public static void main(String[] args) {

        //mergeInto语句模板
        final String template = getTemplate(templatePath);
        //存储mergeInto语句
        mergeIntos = new LinkedList<String>();
        
        // 设置句柄
        DefaultHandler handler = new DefaultHandler() {
            // XML文档开始读取时触发
            public void startDocument() {
                System.out.println("---------XML文档解析开始---------");
            }
            // XML文档读取结束时触发
            public void endDocument() {
                System.out.println("---------XML文档解析结束---------");
            }
            // 读取到某一元素时触发
            public void startElement(String namespaceURI, String lname,
                String qname, Attributes attrs) {
                if (qname.equals("systems")) {
                    System.out.println("文件输出路径:" + attrs.getValue("output"));
                    outputPath = attrs.getValue("output");
                    System.out.println("作者:" + attrs.getValue("author"));
                    author = attrs.getValue("author");
                    System.out.println("备注:" + attrs.getValue("remark"));
                    remark = attrs.getValue("remark");
                } else if (qname.equals("system")) {
                    if (attrs.getValue("enabled").toLowerCase().equals("true")) {
                        System.out.print("读取配置:" + attrs.getValue("name") + "; ");
                        System.out.print("版本号:" + attrs.getValue("version") + "; ");
                        System.out.println("配置号:" + attrs.getValue("config_no"));
                        mergeIntos.add(getMergeInto(template,
                            attrs.getValue("name"), attrs.getValue("version"),
                            attrs.getValue("config_no")));
                    }
                }
            }
        };

        // 使用SAX解析XML
        SAXParserFactory factory = SAXParserFactory.newInstance();
        factory.setNamespaceAware(false);
        try {
            File configFile = new File(configPath);
            SAXParser saxParser = factory.newSAXParser();
            saxParser.parse(configFile, handler);
        } catch (ParserConfigurationException e) {
            e.printStackTrace();
        } catch (SAXException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        outputMergeIntos();
        System.out.println("程序运行结束");
    }

    /**
     * 获取模板
     * 
     * @param templatePath
     * @return
     */
    public static String getTemplate(String templatePath) {
        String template = "";
        try {
            System.out.println("正在输出到文件" + outputPath);
            StringBuilder buffer = new StringBuilder();
            InputStream is = new FileInputStream(templatePath);
            String line;
            BufferedReader reader = new BufferedReader(
                new InputStreamReader(is));
            line = reader.readLine();
            while (line != null) {
                buffer.append(line);
                buffer.append("\n");
                line = reader.readLine();
            }
            template = buffer.toString();
            reader.close();
            is.close();
            System.out.println("输出完毕" + outputPath);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return template;
    }

    /**
     * 通过模板生成对应SQL语句
     * 
     * @param template
     *            模板
     * @param name
     *            配置名
     * @param version
     *            版本号
     * @param configNo
     *            配置号
     * @return
     */
    public static String getMergeInto(String template, String name,
        String version, String configNo) {
        String result = template;
        result = result.replaceAll("\\#\\{name\\}", "'" + name + "'");
        result = result.replaceAll("\\#\\{version\\}", "'" + version + "'");
        result = result.replaceAll("\\#\\{config_no\\}", "'" + configNo + "'");
        return result;
    }
    
    /**
     * 将数据输出到文件
     */
    public static void outputMergeIntos() {
        try {
            System.out.println("正在导出到文件:" + outputPath);
            File outputFile = new File(outputPath);
            BufferedWriter bw = new BufferedWriter(new PrintWriter(outputFile));
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            String currDateTime = sdf.format(new Date());
            bw.append("-----------------------------------------------------\n");
            bw.append("-- 各子系统相关版本号配置项更新\n");
            bw.append("-- 创建时间:" + currDateTime + "\n");
            bw.append("-- 创建人员:" + author + "\n");
            bw.append("-- 备注信息:" + remark + "\n");
            bw.append("-----------------------------------------------------\n");
            bw.newLine();
            for (String mergeInto : mergeIntos) {
                bw.append(mergeInto);
                bw.newLine();
            }
            bw.append("-- 完");
            bw.close();
            System.out.println("导出完毕");
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

三、生成jar包并使用

生成jar包并使用的步骤如下:

1、鼠标右键单击项目,在弹出菜单中点击Export

2、向导页第一页,选择Java→JAR file,点击Next

3、选择刚才正在修改的项目,并在下方“JAR file”位置指定输出的Jar包所在的地址,点击Next

4、这一步直接点击Next

5、点击Browse按钮,指定JAR包入口点

6、找到main函数所在的类,点击OK按钮

7、生成的jar包旁边,建立一个bat文件“GenMergeIntos.bat”,代码如下:

@java -jar GenMergeIntos.jar
@pause

8、运行这个bat文件,运行效果如下:

9、生成的sql文件(updateVer.sql)如下

END

© 著作权归作者所有

共有 人打赏支持
北风其凉

北风其凉

粉丝 114
博文 493
码字总数 462457
作品 4
朝阳
程序员
SWIG与JAVA 交互最全开发指南一

项目背景 最近开始研究做移动端项目,但是本人基本是做了五六年的c++的底层研发,对C++的研发可以说是驾轻就熟了,但是对于android还是属于刚入门阶段,虽然断断续续做移动端也做了一年,但是...

揽月凡尘 ⋅ 06/16 ⋅ 0

gradle/Groovy语法

Groovy官网的介绍(http://www.groovy-lang.org/download.html#gvm) Gradle API 文档: https://docs.gradle.org/current/dsl/org.gradle.api.invocation.Gradle.html 深入理解Android(一)......

shareus ⋅ 04/27 ⋅ 0

mybatis 生成插件的使用

这是在官网看的一段话 上面面圈出来的那段话 :他可以覆盖现有文件或者使用不同的唯一名称保存新生成的文件,我使用生成工具的时候他会覆盖已有重名的java文件,会在已有重名的xml文件中重复...

落后君丶 ⋅ 前天 ⋅ 0

编写高性能 Java 代码的最佳实践

摘要:本文首先介绍了负载测试、基于APM工具的应用程序和服务器监控,随后介绍了编写高性能Java代码的一些最佳实践。最后研究了JVM特定的调优技巧、数据库端的优化和架构方面的调整。以下是译...

这篇文章 ⋅ 06/20 ⋅ 0

java 10 的局部变量类型推导(Local Variable Type Inference )

其实说到变量类型推导,我们很容易连联想到一些脚本语言,在(http://openjdk.java.net/jeps/286)中,java提出这个新特性。 Enhance the Java Language to extend type inference to declar...

woshixin ⋅ 06/16 ⋅ 0

自动化测试selenium在小公司的成功实践

前言 可能提到自动化测试selenium,大家都会想到用python语言来编写脚本。但我们选择了java语言,因为我相信大部分公司java程序员比python程序员多得多。而对于很多测试人员,并不能熟练使用...

邵磊 ⋅ 06/17 ⋅ 0

分享几个JAVA程序员们最容易犯的错误,你中了几枪?

都说Java语言是一门简单的编程语言,基于C++演化而来,剔除了很多C++中的复杂特性,但这并不能保证Java程序员不会犯错。那么对于广大的Java程序员来说,它们最常犯的几个错误都是什么样的呢?...

启示录是真的 ⋅ 05/25 ⋅ 0

Android JNI(一)——NDK与JNI基础

本系列文章如下: Android JNI(一)——NDK与JNI基础 Android JNI学习(二)——实战JNI之“hello world” Android JNI学习(三)——Java与Native相互调用 Android JNI学习(四)——JNI的常用方法...

隔壁老李头 ⋅ 05/09 ⋅ 0

sharding-jdbc源码分析—准备工作

原文作者:阿飞Javaer 原文链接:https://www.jianshu.com/p/7831817c1da8 接下来对sharding-jdbc源码的分析基于tag为源码,根据sharding-jdbc Features深入学习sharding-jdbc的几个主要特性...

飞哥-Javaer ⋅ 05/03 ⋅ 0

资深架构师谈Java——最牛逼的编程语言

有些人问我,在现有的语言里面,有什么好的推荐?我说:“Java。” 他们很惊讶:“什么?Java!” 所以我现在来解释一下。 Java超越了所有咒骂它的“动态语言” 也许是因为年轻人的逆反心理,...

美的让人心动 ⋅ 04/18 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

说说javascript中的那些专业名词

DOM(Document Object Model) 文档对象模型 BOM(Browser Object Model) 浏览器对象模型 ECMA(European Computer Manufacturer's Association) 欧洲计算机制造商协会 W3C(World Wide Web Conso......

hang1989 ⋅ 8分钟前 ⋅ 0

Bootstrap Wizard 多步表单控件

废话 有一块需求是 有多步表单 点击下一步时触发验证一个范围内的表单,点击上一步或取消,清空表单并返回第一步,点击最后一步提交整个表单的 就找到了这个插件,本来自己写了一个原生的 fo...

无极之岚 ⋅ 24分钟前 ⋅ 0

如何利用Spring Cloud构建起自我修复型分布式系统

利用Netflix所打造的组件及各类大家熟知的工具,我们完全可以顺利应对由微服务以及分布式计算所带来的技术挑战。 在过去一年当中,微服务已经成为软件架构领域一个炙手可热的新名词,而且我们...

harries ⋅ 54分钟前 ⋅ 0

临近实习前的感想

再过两星期就要开始新的一段实习了,想想去年的这个时候也在实习,心中不免思绪万千,也一直想写对2017做个总结,但一直迟迟没有下笔。 2017年的春节,我就开始准备开学后找份实习。那时候就...

无精疯 ⋅ 今天 ⋅ 0

Spring AOP(面向切面编程)

Spring AOP概念: Spring AOP 可以劫持一个执行的方法,在方法执行之前或之后添加额外的功能。通常情况下,AOP把项目中需要在多处用到的功能,比如日志、安全和事物等集中到一个类中处理,而...

霍淇滨 ⋅ 今天 ⋅ 0

人工智能、机器学习、数据挖掘以及数据分析有什么联系?

人工智能是目前炙手可热的一个领域,所有的互联网公司以及各路大迦们纷纷表态人工智能将是下一个时代的革命性技术,可与互联网、移动互联网时代的变更相媲美;AlphaGo在围棋领域战胜人类最顶...

董黎明 ⋅ 今天 ⋅ 0

使用 vue-cli 搭建项目

vue-cli 是一个官方发布 vue.js 项目脚手架,使用 vue-cli 可以快速创建 vue 项目,GitHub地址是:https://github.com/vuejs/vue-cli 一、 安装 node.js 首先需要安装node环境,可以直接到中...

初学者的优化 ⋅ 今天 ⋅ 0

设计模式 之 享元模式

设计模式 之 享元模式 定义 使用共享技术来有效地支持大量细粒度对象的复用 关键点:防止类多次创建,造成内存溢出; 使用享元模式来将内部状态与外部状态进行分离,在循环创建对象的环境下,...

GMarshal ⋅ 今天 ⋅ 0

SpringBoot集成Druid的最简单的小示例

参考网页 https://blog.csdn.net/king_is_everyone/article/details/53098350 建立maven工程 Pom文件 <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM......

karma123 ⋅ 今天 ⋅ 0

Java虚拟机基本结构的简单记忆

Java堆:一般是放置实例化的对象的地方,堆分新生代和老年代空间,不断未被回收的对象越老,被放入老年代空间。分配最大堆空间:-Xmx 分配初始堆空间:-Xms,分配新生代空间:-Xmn,新生代的大小一...

算法之名 ⋅ 今天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部