java读取sql脚本文件并插入到mysql数据库
因为项目框架hibernate里的hibernate.hbm2ddl.auto属性设置为create(为了使得开发人员只关注于实体类而不必去关心数据库设计。。。),所以我们每次部署项目的时候都会把数据库生成的表全删除了然后根据实体类生成数据表,这样就需要在maven项目写一个测试类来初始化项目需要的一些基础数据,如用户、权限、资源、字典等。因为maven在构建到特定的生命周期阶段的时候会通过插件来执行JUnit或者TestNG的测试用例,这个插件就是maven-surefire-plugin(这是需要配置的,当然也可以禁止去执行测试类,甚至禁止编译测试类),需要了解的请学习相关maven文档,或者参考http://blog.csdn.net/sin90lzc/article/details/7543262。
考虑到上述因素,那么我就在src/test/java文件夹下新建一个测试类,那么这个测试类就会在clean install时候会执行,那么在这个时候执行数据初始化是合适的。因为初始化数据来自于sql脚本,所以我得读取sql脚本的内容并解析成相关的sql语句通过java的jdbc执行sql语句。那就开始做吧。不多说,上代码:
1
package
com.infopatent.juangetljc.core;
2
3 import java.io.BufferedReader;
4 import java.io.FileInputStream;
5 import java.io.InputStream;
6 import java.sql.Connection;
7 import java.sql.DriverManager;
8 import java.sql.SQLException;
9 import java.sql.Statement;
10 import java.util.ArrayList;
11 import java.util.Arrays;
12 import java.util.List;
13
14 import org.junit.Test;
15
16 import junit.framework.TestCase;
17
18 public class InitDataTest extends TestCase {
19
20 private String url = " jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8 " ;
21 private String driver = " com.mysql.jdbc.Driver " ;
22 private String userName = " root " ;
23 private String password = "" ;
24 String filePathIn = " F://workspace/juange-tljc/juange-tljc-core/src/test/java/basedata.sql " ;
25
26 @Test
27 public void test() {
28
29 try {
30 execute(filePathIn);
31 } catch (Exception e) {
32 // TODO Auto-generated catch block
33 e.printStackTrace();
34 }
35 }
36
37 /*
38 * 读取sql文件,获取sql语句
39 * 返回所有sql语句的list集合
40 * */
41 private List < String > loadSql(String sqlFile) throws Exception {
42 List < String > sqlList = new ArrayList < String > ();
43 /*
44 * 读取文件的内容并写道StringBuffer中去
45 * */
46 InputStream sqlFileIn = new FileInputStream(sqlFile);
47 StringBuffer sqlSb = new StringBuffer();
48 byte [] buff = new byte [sqlFileIn.available()];
49 int byteRead = 0 ;
50 while ((byteRead = sqlFileIn.read(buff)) != - 1 ) {
51 sqlSb.append( new String(buff, 0 , byteRead));
52 }
53 /*
54 * windows下换行是/r/n,Linux下是/n,
55 * 此处需要根据导出的sql文件进行具体的处理,我在处理的时候
56 * 也遇到了很多的问题,如果我这个不行可以在网上找找别的解析方法
57 * */
58 String sqlArr[] = sqlSb.toString().split( " (;\\s*\\rr\\n)|(;\\s*\\n) " );
59 for ( int i = 0 ; i < sqlArr.length; i ++ ) {
60 String sql = sqlArr[i].replaceAll( " --.* " , "" ).trim();
61 if ( ! "" .equals(sql)) {
62 sqlList.add(sql);
63 }
64 }
65 return sqlList;
66
67 }
68
69 /*
70 * 传入文件执行sql语句
71 *
72 * */
73 private void execute(String sqlFile) throws SQLException {
74 Statement stmt = null ;
75 List < String > sqlList = new ArrayList < String > ();
76 Connection conn = getConnection();
77 try {
78 sqlList = loadSql(sqlFile);
79 conn.setAutoCommit( false );
80 stmt = conn.createStatement();
81 for (String sql : sqlList) {
82 System.out.println(sql);
83 stmt.addBatch(sql);
84 }
85 int [] rows = stmt.executeBatch();
86 System.out.println( " Row count: " + Arrays.toString(rows));
87 conn.commit();
88 System.out.println( " 数据更新成功 " );
89 } catch (Exception e) {
90 e.printStackTrace();
91 conn.rollback();
92 } finally {
93 stmt.close();
94 conn.close();
95 }
96
97 }
98
99 /*
100 * 获取sql连接
101 * */
102 private Connection getConnection(){
103 Connection conn = null ;
104 try {
105 Class.forName(driver);
106 conn = DriverManager.getConnection(url, userName, password);
107 if ( ! conn.isClosed()) {
108 System.out.println( " 数据库连接成功! " );
109 }
110 } catch (Exception e) {
111 e.printStackTrace();
112 }
113 return conn;
114 }
115 }
116
2
3 import java.io.BufferedReader;
4 import java.io.FileInputStream;
5 import java.io.InputStream;
6 import java.sql.Connection;
7 import java.sql.DriverManager;
8 import java.sql.SQLException;
9 import java.sql.Statement;
10 import java.util.ArrayList;
11 import java.util.Arrays;
12 import java.util.List;
13
14 import org.junit.Test;
15
16 import junit.framework.TestCase;
17
18 public class InitDataTest extends TestCase {
19
20 private String url = " jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8 " ;
21 private String driver = " com.mysql.jdbc.Driver " ;
22 private String userName = " root " ;
23 private String password = "" ;
24 String filePathIn = " F://workspace/juange-tljc/juange-tljc-core/src/test/java/basedata.sql " ;
25
26 @Test
27 public void test() {
28
29 try {
30 execute(filePathIn);
31 } catch (Exception e) {
32 // TODO Auto-generated catch block
33 e.printStackTrace();
34 }
35 }
36
37 /*
38 * 读取sql文件,获取sql语句
39 * 返回所有sql语句的list集合
40 * */
41 private List < String > loadSql(String sqlFile) throws Exception {
42 List < String > sqlList = new ArrayList < String > ();
43 /*
44 * 读取文件的内容并写道StringBuffer中去
45 * */
46 InputStream sqlFileIn = new FileInputStream(sqlFile);
47 StringBuffer sqlSb = new StringBuffer();
48 byte [] buff = new byte [sqlFileIn.available()];
49 int byteRead = 0 ;
50 while ((byteRead = sqlFileIn.read(buff)) != - 1 ) {
51 sqlSb.append( new String(buff, 0 , byteRead));
52 }
53 /*
54 * windows下换行是/r/n,Linux下是/n,
55 * 此处需要根据导出的sql文件进行具体的处理,我在处理的时候
56 * 也遇到了很多的问题,如果我这个不行可以在网上找找别的解析方法
57 * */
58 String sqlArr[] = sqlSb.toString().split( " (;\\s*\\rr\\n)|(;\\s*\\n) " );
59 for ( int i = 0 ; i < sqlArr.length; i ++ ) {
60 String sql = sqlArr[i].replaceAll( " --.* " , "" ).trim();
61 if ( ! "" .equals(sql)) {
62 sqlList.add(sql);
63 }
64 }
65 return sqlList;
66
67 }
68
69 /*
70 * 传入文件执行sql语句
71 *
72 * */
73 private void execute(String sqlFile) throws SQLException {
74 Statement stmt = null ;
75 List < String > sqlList = new ArrayList < String > ();
76 Connection conn = getConnection();
77 try {
78 sqlList = loadSql(sqlFile);
79 conn.setAutoCommit( false );
80 stmt = conn.createStatement();
81 for (String sql : sqlList) {
82 System.out.println(sql);
83 stmt.addBatch(sql);
84 }
85 int [] rows = stmt.executeBatch();
86 System.out.println( " Row count: " + Arrays.toString(rows));
87 conn.commit();
88 System.out.println( " 数据更新成功 " );
89 } catch (Exception e) {
90 e.printStackTrace();
91 conn.rollback();
92 } finally {
93 stmt.close();
94 conn.close();
95 }
96
97 }
98
99 /*
100 * 获取sql连接
101 * */
102 private Connection getConnection(){
103 Connection conn = null ;
104 try {
105 Class.forName(driver);
106 conn = DriverManager.getConnection(url, userName, password);
107 if ( ! conn.isClosed()) {
108 System.out.println( " 数据库连接成功! " );
109 }
110 } catch (Exception e) {
111 e.printStackTrace();
112 }
113 return conn;
114 }
115 }
116
在这个过程中遇到了很多的问题,曾经一度使我陷入迷糊状态中,后来好好梳理了一下思路,一个一个的去排查问题终于成功了~
首先在读取文件的时候,发现读取的文件内容显示是正常的不是乱码,但是插入到数据库中就是乱码,好吧,我又遇到了这种问题,我依次检查了我java文件的编码,数据库的编码,都设置为utf-8,url也加上编码 " jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8 "。结果还是乱码,那就再看看mysql下的my.ini文件中的编码设置在[mysqld]节点下加上default-character-set=utf8(如果没有就改为utf8),这下终于不是乱码了。然后我开始maven clean install,去查看数据库发现又出现了乱码的问题,真是折磨人啊,我发现唯一不同的就是之前正常的插入数据是我在测试类下run as junit,而现在用的是maven clean install,刚接触maven完全不知道症结所在啊,百度一下,发现maven构建到特定的生命周期时候运行测试用例是依靠maven-surefire-plugin这个插件的,而这个插件也需要指定字符集编码的,于是我在项目的pom.xml中加入了如下代码(本来竟然没有!):
1
<
build
>
2 < plugins >
3 < plugin >
4 < groupId > org.apache.maven.plugins </ groupId >
5 < artifactId > maven-surefire-plugin </ artifactId >
6 < version > 2.7.2 </ version >
7 < configuration >
8 < forkMode > once </ forkMode >
9 < argLine > -Dfile.encoding=UTF-8 </ argLine >
10 < systemProperties >
11 < property >
12 < name > net.sourceforge.cobertura.datafile </ name >
13 < value > target/cobertura/cobertura.ser </ value >
14 </ property >
15 </ systemProperties >
16 </ configuration >
17 </ plugin >
18 </ plugins >
19 </ build >
2 < plugins >
3 < plugin >
4 < groupId > org.apache.maven.plugins </ groupId >
5 < artifactId > maven-surefire-plugin </ artifactId >
6 < version > 2.7.2 </ version >
7 < configuration >
8 < forkMode > once </ forkMode >
9 < argLine > -Dfile.encoding=UTF-8 </ argLine >
10 < systemProperties >
11 < property >
12 < name > net.sourceforge.cobertura.datafile </ name >
13 < value > target/cobertura/cobertura.ser </ value >
14 </ property >
15 </ systemProperties >
16 </ configuration >
17 </ plugin >
18 </ plugins >
19 </ build >
这个时候再去maven clean install,终于不乱码了,终于不乱码了!花了我四个小时,长见识了!此处记录自己遇到的问题以及如何解决,希望对各位有帮助!