背景 :通过程序来执行sql脚本实现数据库的初始化功能

选择的工具如下

<!-- ibatis工具包oracle的初始化 -->
	<dependency>
	    <groupId>com.ibatis</groupId>
	    <artifactId>ibatis2-common</artifactId>
	    <version>2.1.7.597</version>
	</dependency>
	<!-- ibatis工具包sqlserver的初始化 -->
	<dependency>  
        <groupId>org.mybatis</groupId>  
        <artifactId>mybatis</artifactId>  
        <version>3.3.0</version>  
    </dependency>
之所以会用上两个jar是因为使用过程中发现ibatis的不能指定sql语句分隔符,对Navicat导出的sqlserver脚本支持不是很好,可能是个人没努力找解决方法导致的,反正我是换了一个mybatis的包才处理的,宁外发现mybatis执行sql脚本时不允许脚本中有.号(点号)navicat导出的脚本注释是脚本是含点号的故又不兼容oracle了,(但是如果你的注释写在创建表语句中也就是跟在字段后面添加注释的也就是不带点号的形式是可以的)

我这里都是通过navicat导出的脚本所以就采用了两个jar包通过数据库类型的方式方别引入不同jar来实现的兼容  代码如下:

package com.noteshare.common.kit.initsystem.services;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Comparator;
import java.util.List;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

import org.apache.ibatis.jdbc.ScriptRunner;

import com.noteshare.common.util.DBUtil;
import com.noteshare.platform.util.dao.JdbcDAO;

import edu.emory.mathcs.backport.java.util.Arrays;
import edu.emory.mathcs.backport.java.util.Collections;

/**
 *  初始化数据库兼容器
 */
public class InitDatebaseListener implements ServletContextListener {

    /**
     * 应用程序启动事件
     */
    public void contextInitialized(ServletContextEvent event) {
        System.out.println("================开始初始化应用数据库,请在初始化之前先建立好数据库、表空间和数据库用户,并分配好相关权限=========================");
        Connection conn = null;
        try {
            String databaseType = null;
            while (null == databaseType) {
                System.out.println("========请输入(或重新输入)数据库类型,按上面给出的类型输入====");
                databaseType = writeDatabaseType();
            }
            JdbcDAO dao = new JdbcDAO();
            conn = dao.getConnection();
            // 获取数据库连接
            /*
             * while(null == conn){ conn = getConnection(); }
             */
            // 判断是否已经初始化过
            boolean flag = hasInited(databaseType, conn);
            if (!flag) {
                // 执行数据库初始化脚本
                executeInitSql(databaseType, conn);
                System.out.println("================数据库初始化结束,请修改数据源然后重启系统检测初始化效果,其他信息的初始化请到系统里面找到相关的初始化功能再进行初始化,比如:orgid的初始化等等。==========");
            } else {
                System.out.println("================您输入的连接所代表的数据并非是个空库,为了安全起见我们不能给你初始化,请建立新的空库,然后再来初始化!!!请谅解我不能同意你做这么不安全的事情!!!");
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (null != conn) {
                try {
                    DBUtil.closeCon(conn);
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    private String writeDatabaseType() throws Exception {
        System.out.println("请输入数据库类型字符串,目前支持以下几种,请选择你的数据库类型(oracle、sqlserver2008、sqlserver2012)");
        System.out.println("数据库类型为databaseName=");
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String type = br.readLine();
        if (null == type || (!type.equals("oracle") && !type.equals("sqlserver2008") && !type.equals("sqlserver2012"))) {
            return null;
        } else {
            return type;
        }
    }

    /**
     * 获取数据连接
     * @return Connection conn
     */
    @SuppressWarnings("unused")
    private Connection getConnection() {
        Connection conn = null;
        try {
            /*
             * jdbc.oracle.driver=oracle.jdbc.driver.OracleDriver
             * jdbc.oracle.url=jdbc:oracle:thin:@localhost:1521:ORCL
             * jdbc.oracle.username=U_XMSP_20170629
             * jdbc.oracle.password=U_XMSP_20170629
             */
            System.out.println("==1:输入数据库相关连接信息===============");
            // 判断是否要初始化数据库
            BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
            System.out.print("请输入数据库驱动(注意不要输入多余的空白字符哦):driver=");
            String driver = br.readLine();
            System.out.println("请输入数据库连接url:url=");
            String url = br.readLine();
            System.out.println("请输入数据库用户名:username=");
            String username = br.readLine();
            System.out.println("请输入数据密码:password=");
            String password = br.readLine();
            // 创建数据库连接
            conn = DBUtil.getConnection(driver, url, username, password);
        } catch (Exception e) {
            System.out.println("创建数据库连接失败,请检查输入的连接信息是否有误,并重新输入!" + e.getMessage());
        }
        return conn;
    }

    @Override
    public void contextDestroyed(ServletContextEvent arg0) {

    }

    /**
     * 执行数据库初始化脚本
     * 注意:文件应该有执行顺序,我们是按文件的时间的升序顺序执行的,文件名请以时间命名,并按例子的格式书写文件名,我们只执行.sql文件
     * @param conn
     * @throws Exception 
     */
    private void executeInitSql(String databaseType, Connection conn) throws Exception {
        try {
            long start = System.currentTimeMillis();
            System.out.println("------(1):开始执行数据库初始化脚本------");
            // 调用指令执行初始化数据
            String currPath = InitDatebaseListener.class.getResource("").getFile();
            currPath = currPath.substring(1, currPath.length());
            currPath = currPath.replace("services/", "initsql/");
            // 拼接上数据库类型文件夹
            currPath = currPath + databaseType + "/";
            File file = new File(currPath);
            File[] files = file.listFiles();
            if (null != files) {
                // 对初始化文件进行排序
                @SuppressWarnings("unchecked")
                List<File> fileList = Arrays.asList(files);
                Collections.sort(fileList, new Comparator<File>() {
                    @Override
                    public int compare(File o1, File o2) {
                        String file1Name = o1.getName();
                        String file2Name = o2.getName();
                        return file1Name.compareTo(file2Name);
                    }
                });
                for (File file2 : fileList) {
                    if (file2.getName().contains(".sql")) {
                        long startFileTime = System.currentTimeMillis();
                        System.out.println("------开始执行" + file2.getName() + "脚本文件。------");
                        // false);
                        if (databaseType.contains("sqlserver")) {
                            ScriptRunner runner = new ScriptRunner(conn);
                            // 下面的配置,不要随意更改,否则导致各种问题
                            runner.setAutoCommit(true);// 自动提交
                            runner.setFullLineDelimiter(true);
                            runner.setDelimiter("GO");// 每条命令间的分隔符
                            runner.setSendFullScript(false);
                            runner.setStopOnError(false);
                            File errorFile1 = new File(currPath + "/" + file2.getName().replace(".sql", "error") + ".log");
                            runner.setErrorLogWriter(new PrintWriter(errorFile1));
                            runner.setLogWriter(new PrintWriter(new File(currPath + "/" + file2.getName().replace(".sql", "_alllog") + ".log")));
                            System.out.println("日志文件路径为:");
                            System.out.println(currPath + "/" + file2.getName().replace(".sql", "error") + ".log");
                            System.out.println(currPath + "/" + file2.getName().replace(".sql", "_alllog") + ".log");
                            runner.runScript(new InputStreamReader(new FileInputStream(file2), "utf8"));
                        } else {
                            //oracle用的是ibatis,mybatis那个不支持导入表的注释
                            com.ibatis.common.jdbc.ScriptRunner runner = new com.ibatis.common.jdbc.ScriptRunner(conn, true, false);
                            File errorFile1 = new File(currPath + "/" + file2.getName().replace(".sql", "error") + ".log");
                            runner.setErrorLogWriter(new InputStreamReader(new FileInputStream(file2), "utf8"));
                            runner.setLogWriter(new PrintWriter(new File(currPath + "/" + file2.getName().replace(".sql", "_alllog") + ".log")));
                            System.out.println("日志文件路径为:");
                            System.out.println(currPath + "/" + file2.getName().replace(".sql", "error") + ".log");
                            System.out.println(currPath + "/" + file2.getName().replace(".sql", "_alllog") + ".log");
                            runner.runScript(new FileReader(file2));
                        }
                        long endFileTime = System.currentTimeMillis();
                        System.out.println("------执行此《" + file2.getName() + ".sql》文件共花费时间" + (endFileTime - startFileTime));
                    }
                }
            }
            long end = System.currentTimeMillis();
            System.out.println("执行初始化脚本共花费时间:" + (end - start) + "毫秒。");
        } catch (Exception e) {
            throw e;
        }
    }

    /**
     * 执行数据库更新脚本
     * @param conn
     */
    @SuppressWarnings("unused")
    private void executeUpdateSql(Connection conn) {
        // TODO:执行数据库更新脚本-此功能后续根据实际需求再完善,暂时不开发。
    }

    /**
     * 为了防止往非空库里面初始化导致数据丢失的问题,我们特提供此方法来检测数据库是否是一个新建的库,
     * @param databaseType
     * @param conn
     * @return 返回true代表已经初始化过(或者输入数据库类型不支持),返回false则代表是一个新库.
     */
    private boolean hasInited(String databaseType, Connection conn) {
        boolean flag = true;
        // select count(*) num from user_tables
        // SELECT count(*) FROM SysObjects Where XType='U'
        String sql = null;
        String oracleSql = "SELECT COUNT(*) NUM FROM USER_TABLES";
        String sqlserverSql = "SELECT COUNT(*) NUM FROM SYSOBJECTS WHERE XTYPE='U'";
        PreparedStatement pstmt = null;
        if (databaseType.startsWith("oracle")) {
            sql = oracleSql;
        } else if (databaseType.startsWith("sqlserver")) {
            sql = sqlserverSql;
        }
        try {
            pstmt = conn.prepareStatement(sql);
            ResultSet rs = pstmt.executeQuery();
            rs.next();
            int num = rs.getInt("NUM");
            if (num <= 0) {
                flag = false;
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return flag;
    }
    
    /**
     * @param args
     * @throws Exception
     */
    public static void main(String[] args) throws Exception {
        File file = new File("D:/eclipseWorkspace/pure3.1/src/main/java/com/noteshare/common/kit/initsystem/initsql");
        File[] files = file.listFiles();
        @SuppressWarnings("unchecked")
        List<File> list = Arrays.asList(files);
        Collections.sort(list, new Comparator<File>() {
            @Override
            public int compare(File o1, File o2) {
                String file1Name = o1.getName();
                String file2Name = o2.getName();
                return file1Name.compareTo(file2Name);
            }
        });
        for (File file2 : list) {
            System.out.println(file2.getName());
        }
        /*
         * initDatebaseListener initObj = new initDatebaseListener(); Connection
         * conn = initObj.getConnection();
         * System.out.println(conn.getCatalog());
         * System.out.println(conn.getSchema());
         */
    }
}


作者:星辰 时间:2017-08-03 浏览 675评论 0 赞 0砸 0 标签: Java基础知识 oracle sqlserver java组件 数据库编程
评论
还可以再输入500个字

请您注意

·自觉遵守:爱国、守法、自律、真实、文明的原则
·尊重网上道德,遵守《全国人大常委会关于维护互联网安全的决定》及中华人民共和国其他各项有关法律法规
·严禁发表危害国家安全,破坏民族团结、国家宗教政策和社会稳定,含侮辱、诽谤、教唆、淫秽等内容的作品
·承担一切因您的行为而直接或间接导致的民事或刑事法律责任
·您在NoteShare上发表的作品,NoteShare有权在网站内保留、转载、引用或者删除
·参与本评论即表明您已经阅读并接受上述条款