在做软件部署或者安装的时候,有时候需要手动去导入数据库的sql脚本,涉及到多个库的时候手动太low,这里做了一个简单的建表建库操作。我们这里主要用到的方法是:mybatis ScriptRunner:
这里我们直接通过jdbc去写入建表的语句,实际项目中直接用mybatis语句建立数据库,然后通过 ScriptRunner导入sql脚本。
下面介绍两种方法,一种直接导入,一种直接执行sql,实际上对sql进行拆分,批量执行而已。(如果是脚本,两种方法一样,建议直接用第一种,简单粗暴)
package cn.ivg.controller;
import java.nio.charset.Charset;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.jdbc.ScriptRunner;
import lombok.extern.slf4j.Slf4j;
/**
* Project Name:cscm-base-vipshop
* File Name:SqlTest.java
* Package Name:
* Date:2019年7月27日下午9:55:48
* Copyright (c) 2019, bluemobi All Rights Reserved.
*
*/
/**
* Description:
* Date: 2019年7月27日 下午9:55:48
*
* @author xuC
* @version
* @see
*/
@Slf4j
public class SqlTest {
public static void main(String[] args) {
connmysql("sql/ceshi.sql", "xucan");
log.info("执行成功!");
}
private static void connmysql(String sqlPath, String dataName) {
Connection conn;
Connection newConn;
String url = "jdbc:mysql://127.0.0.1:3306/cloud_log?characterEncoding=utf8&useSSL=true";
String username = "root";
String password = "root";
String driver = "com.mysql.jdbc.Driver";
try {
newConn = DriverManager.getConnection(url, username, password);
Class.forName(driver).newInstance();
String databaseSql = "CREATE DATABASE IF NOT EXISTS " + dataName
+ " DEFAULT CHARSET utf8mb4 COLLATE utf8mb4_general_ci;";
Statement smt = newConn.createStatement();
smt.executeUpdate(databaseSql);
log.info("----------数据库{}创建成功", dataName);
String realUrl = getData(url) + dataName;
conn = DriverManager.getConnection(realUrl, username, password);
ScriptRunner runner = new ScriptRunner(conn);
Resources.setCharset(Charset.forName("utf-8")); // 设置字符集,不然中文乱码插入错误
// runner.setAutoCommit(true);// false设置不自动提交
runner.setStopOnError(true);// (1)false,遇见错误不会停止,会继续执行,会打印异常信息,并不会抛出异常,当前方法无法捕捉异常无法进行回滚操作,无法保证在一个事务内执行;(2)true,遇见错误会停止执行,打印并抛出异常,捕捉异常,并进行回滚,保证在一个事务内执行;
// runner.setSendFullScript(true);// (如果没有自定义最好注释,不然容易报错)按照那种方式执行 方式一:true则获取整个脚本并执行 方式二:false则按照自定义的分隔符每行执行;
// runner.setLogWriter(null);// 设置是否输出日志,null不输出日志,不设置自动将日志输出到控制台
runner.runScript(Resources.getResourceAsReader(sqlPath));// 在resouse中新建一个文件夹:然后放入sql文件
log.info("数据库{}脚本执行成功", dataName);
smt.close();
runner.closeConnection();
newConn.close();
conn.close();
} catch (Exception e) {
e.printStackTrace();
}
}
private static String getData(String url) {
return url.substring(0, url.lastIndexOf("/") + 1);
}
}
/**
* Project Name:cscm-base-vipshop
* File Name:SqlHelper.java
* Package Name:cn.ivg.controller
* Date:2019年7月28日上午12:45:08
* Copyright (c) 2019, bluemobi All Rights Reserved.
*
*/
package cn.ivg.controller;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.apache.ibatis.io.Resources;
/*
* 使用java以及jdbc执行sql脚本的工具示例代码
*/
public class SqlHelper {
public static void main(String[] args) throws IOException {
String path = Resources.getResourceAsFile("sql/ceshi.sql").getAbsolutePath();
String sql = getText(path);
List sqlarr = getSql(sql);
for (String string : sqlarr) {
System.out.println(string);
}
try {
SqlHelper.execute(getConn(), sqlarr);
} catch (Exception e) {
e.printStackTrace();
}
}
public static void execute(Connection conn, List sqlFile) throws Exception {
Statement stmt = null;
stmt = conn.createStatement();
for (String sql : sqlFile) {
sql = sql.trim();
if (sql != null && !sql.equals(""))
stmt.addBatch(sql);
}
int[] rows = stmt.executeBatch();
System.out.println("Row count:" + Arrays.toString(rows));
conn.close();
}
private static Connection getConn() {
String url = "jdbc:mysql://127.0.0.1:3306/xucan?characterEncoding=utf8&useSSL=true";
String username = "root";
String password = "root";
String driver = "com.mysql.jdbc.Driver";
Connection conn = null;
try {
Class.forName(driver); // classLoader,加载对应驱动
conn = DriverManager.getConnection(url, username, password);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
return conn;
}
/*
* getText方法吧path路径里面的文件按行读数来放入一个大的String里面去 并在换行的时候加入\r\n
*/
public static String getText(String path) {
File file = new File(path);
if (!file.exists() || file.isDirectory()) {
return null;
}
StringBuilder sb = new StringBuilder();
try {
FileInputStream fis = new FileInputStream(path);
InputStreamReader isr = new InputStreamReader(fis, "UTF-8");
BufferedReader br = new BufferedReader(isr);
String temp = null;
temp = br.readLine();
boolean flag = true;
while (temp != null) {
if (temp.length() >= 2) {
String str1 = temp.substring(0, 1);
String str2 = temp.substring(0, 2);
if (str1.equals("#") || str2.equals("--") || str2.equals("//")) {
temp = br.readLine();
continue;
}
if (str2.equals("/*")) {// 因为/**/是注释有/*时,直到遇到*/才开始添加
flag = false;
}
if (str2.equals("*/")) {
flag = true;
temp = "";
}
if (flag) {
sb.append(temp + "\r\n");
}
}
temp = br.readLine();
}
br.close();
} catch (Exception e) {
e.printStackTrace();
}
return sb.toString();
}
/*
* getSqlArray方法 从文件的sql字符串中分析出能够独立执行的sql语句并返回
*/
public static List getSql(String sql) {
String s = sql;
s = s.replaceAll("\r\n", "\r");
s = s.replaceAll("\r", "\n");
List ret = new ArrayList();
String[] sqlarry = s.split(";"); // 用;把所有的语句都分开成一个个单独的句子
sqlarry = filter(sqlarry);
ret = Arrays.asList(sqlarry);
return ret;
}
public static String[] filter(String[] ss) {
List strs = new ArrayList();
for (String s : ss) {
if (s != null && !s.equals("")) {
strs.add(s);
}
}
String[] result = new String[strs.size()];
for (int i = 0; i < strs.size(); i++) {
result[i] = strs.get(i).toString();
}
return result;
}
}
以上就是两种不同实现方法,如果是数据库直接导出的用第一种就好了 。第二种是为了方便那种无法直接导入数据库的脚本去实现的。