最近在做系统数据初始化,采用sql形式导入基础数据,这里记录下编码过程。

导出的sql文件已经放在dao目录下了。

先来写个方法读取sql文件:

/**
* 加载解析sql文件
* @param sqlFile
* @return
* @throws Exception
*/
private static List<String> loadSql(String sqlFile) throws Exception {
List<String> sqlList = new ArrayList<String>();
try {
InputStream sqlFileIn = new FileInputStream(sqlFile);
StringBuffer sqlSb = new StringBuffer();
byte[] buff = new byte[1024];
int byteRead = 0;
while ((byteRead = sqlFileIn.read(buff)) != -1) {
sqlSb.append(new String(buff, 0, byteRead,"utf-8"));
}
sqlFileIn.close();
// Windows 下换行是 \r\n, Linux 下是 \n
String[] sqlArr = sqlSb.toString()
.split("(;\\s*\\r\\n)|(;\\s*\\n)");
for (int i = 0; i < sqlArr.length; i++) {
String sql = sqlArr[i].replaceAll("--.*", "").trim();
if (!sql.equals("")) {
sqlList.add(sql);
}
}
return sqlList;
} catch (Exception ex) {
throw new Exception(ex.getMessage());
}
}

即把sql文件读取出来,解析成单条sql语句。

下面是action执行方法

/**
* 执行sql,初始化系统基础数据
* @return
*/
public Object init(){
List<String> list = new ArrayList<String>();
try {
list = loadSql("D:\\workspace\\com.leadal.netiler.install\\web\\data\\dao\\newclips.sql");
int i=0;
service.setProgess(0);
service.setExecute(true);
int size = list.size();
for(String sql:list){
if(!service.getExecute()){
service.setProgess(100);
break;
}
service.executeSql(sql);
i++;
service.setProgess(100*i/size);
}
ActionMessage.info("基础数据初始化成功!");
} catch (Exception e) {
e.printStackTrace();
ActionMessage.error("初始化失败!");
}
return this;
}

由于是测试,sql文件直接写了个绝对路径。

service调用dao的executeSql(String sql)方法

netiler dao:

@Dao("Netiler.Install.Init.InitBasicData")
public interface InitBasicDataDao {
@Paramable("sql")
public void executeSql(String sql);
}

Netiler Dao dao文件写法:

<?xml version="1.0" encoding="UTF-8" ?>
<sql>
<result id="result" auto="true">
</result>
<statement id="executeSql"  result="result">
<![CDATA[
#parse($sql)
]]>
</statement>
</sql>

这里使用statement,定义了个自动类型的result。

过程中遇到几个问题,一个是返回值的,另一个是sql文件包含指令如#if()时,#if()括号里为空字符,解析时有点问题,最后把#if()换成#if(1==1)


2013/5/31 10:35 补充与修改:

在数据插入后,发现部分中文数据是乱码的,经过初步分析,乱码的位置都很有规律,即总是固定的位置出现中文乱码了。这里得到结果是,字节流解析的时候没有处理中文的问题,因为汉字是占两个字节的,当一个汉字刚好占1024-1025字节时,汉字就被拆开了。

解决的方法有两种,一种是继续使用字节流解析,但是对汉字需要进行特殊处理,即通过对比ASCII码大小来确定是否是汉字而进行拼接操作。这样显然是比较麻烦的,当然肯定可以实现。

这里笔者采用字符流行读取形式进行读取解析,贴上代码

    /**
     * 加载解析sql 读取方式字符流 行读取
     * @param sqlFile
     * @return
     * @throws Exception
     */
    private List<String> loadSql2(String sqlFile) throws Exception{
        List<String> sqlList = new ArrayList<String>();
        try {
            FileReader fr = new FileReader(sqlFile);
            BufferedReader br = new BufferedReader(fr);
            String s="";
            StringBuffer sb = new StringBuffer();
            while ((s = br.readLine()) != null) {
                if(s.startsWith("/*")||s.startsWith("--")){
                       
                }
                else if(s.endsWith(";")){
                    sb.append(s);
                    sqlList.add(sb.toString());
                    sb.delete(0, sb.length());
                }
                else{
                    sb.append(s);
                }
                               
            }
            fr.close();
            br.close();
//          for(String sql : sqlList){
//              System.out.println("sql:"+sql);
//          }
        } catch (Exception e) {
            throw new Exception(e.getMessage());
        }
        return sqlList;    
    }

经过测试,乱码问题得到解决