文档章节

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

北风其凉
 北风其凉
发布于 2016/02/17 00:13
字数 1566
阅读 2.2K
收藏 9

#程序员薪资揭榜#你做程序员几年了?月薪多少?发量还在么?>>>

一、工具的制作背景

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

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

© 著作权归作者所有

北风其凉

北风其凉

粉丝 124
博文 497
码字总数 462305
作品 4
朝阳
程序员
私信 提问
加载中

评论(0)

9个杀手级 JVM 编程语言

Java虚拟机已经不再是仅仅局限在 Java 了,很多语言提供了脚本转换,可以让其他的程序在java虚拟机上运行,这样能够让更多的开发者能够依靠JVM在Java平台上大有作为。而且虚拟机以及 对应的字...

彭博
2012/11/27
1K
0
是C#语言比Java语言好还是你自己的问题

阅读全文:http://www.sufeinet.com/thread-1710-1-1.html 是C#语言比Java语言好还是你自己的问题 c#语言和java语言那个好 其实我一听到这个话题就感觉无奈,但是最近博客园这种类似的问题还...

苏飞博客
2012/12/06
0
0
2018蓝旭后端培训之JDBC

前言:在学习jdbc之前推荐大家再次学学常用的SQL语句,熟悉java API文档的查看 一.什么是JDBC jdbc即Java Database Conection,java数据库连接,是一种用于执行SQL语句的Java API,可以为多种...

浪舟子
03/31
0
0
推荐 IntelliJ IDEA 牛逼的插件

activate-power-mode 和 Power mode II 根据Atom的插件activate-power-mode的效果移植到IDEA上 写代码是整个屏幕都在抖动,activate-power-mode是白的的,Power mode II色彩更酷炫点。 2.Ba...

osc_fjbsh38p
2019/04/30
2
0
秒懂Java动态编程(Javassist研究)

[toc] 概述 什么是动态编程?动态编程解决什么问题?Java中如何使用?什么原理?如何改进?(需要我们一起探索,由于自己也是比较菜,一般深入不到这个程度)。 什么是动态编程 动态编程是相...

MyOldTime
2019/07/03
127
0

没有更多内容

加载失败,请刷新页面

加载更多

时间片轮询法

时间片轮询法 时间片轮询法是一种比较简单易用的系统架构之一,它对于系统中的任务调度算法是分时处理。核心思路是把 CPU 的时间分时给各个任务使用。我们常用的定时方法是定时器,把调度器放...

osc_j7rfhwi0
50分钟前
15
0
二项堆(三)之 Java的实现

概要 前面分别通过C和C++实现了二项堆,本章给出二项堆的Java版本。还是那句老话,三种实现的原理一样,择其一了解即可。 目录 1. 二项树的介绍 2. 二项堆的介绍 3. 二项堆的基本操作 4. 二项...

osc_ct8a6sdg
50分钟前
9
0
Windows 10 安装 Hadoop 2.10

  1. 配置JAVA_HOME环境和Hadoop环境:      2. 配置bin   3. 进入Hadoop中/etc/hadoop下     配置hdfs-site.xml增加:    <property> <!-- 单节点,所以配置成1 -->...

osc_jmtenr3d
51分钟前
32
0
如何让你在众多二手车中挑中满意的?python帮你实现(附源码)

前言 老司机带你去看车,网上的几千条的二手车数据,只需几十行代码,就可以统统获取,保存数据到我们本地电脑上 知识点: 1.python基础知识 2.函数 3.requests库 4.xpath适合零基础的同学 ...

osc_rmqoxylv
52分钟前
12
0
Selenium IDE使用指南三(控制流)

Selenium IDE附带的命令使您可以添加条件逻辑和循环到测试中。 这使您仅在满足应用程序中的某些条件时才执行命令(或一组命令),或根据预定义的标准重复执行命令。 JavaScript表达式 通过使...

分布式编程
52分钟前
17
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部