Java代码中如何调用Ant的SQLExec类执行SQL脚本,最后考虑ant.jar的个头说大也不小,1M多,如果只用于执行SQL脚本,则绝大部分代码就是垃圾,所以从同抽离出需要的两个类JDBCTask和SQLExec,完全去除了对ant.jar包的依赖。

AD:


前面记载过一篇Java执行SQL脚本文件,这里边完全是由自己写代码来分离出脚本中的每一个SQL语句的,有不少缺陷。当时还不太清楚ANT本身提供了功能很强的执行SQL语句和脚本的SQL Task可用。以下依次简单介绍如何在 build.xml 中执行SQL语句或脚本;Java代码中如何调用ANT的SQLExec类执行SQL脚本,最后考虑 ant.jar的个头说大也不小,1M 多,如果只用于执行SQL脚本,则绝大部分代码就是垃圾,所以从同抽离出需要的两个类JDBCTask和 SQLExec,完全去除了对ant.jar包的依赖。

1、build.xml 中执行sql 脚本

autocommit="true"  
url="jdbc:oracle:thin:@10.128.x.x:1521:xxsid" src="data.sql" print="yes" output= 

"sql_out.txt">  

autocommit="true" 
url="jdbc:oracle:thin:@10.128.x.x:1521:xxsid" src="data.sql" print="yes" output= 

"sql_out.txt">



也可以在 ...  中直接包含一条或多条 sql 语句,默认分号分隔。脚本文件 data.sql 中可以写多个语句,也是默认分号分隔,可含 -- 注释符。说白了就是基本在 PL/SQL Developer 中可以怎么写,你的脚本文件中也可以怎么写,并且还能支持象 MySQL 的 // 那样的注释符。

像如下那样的SQL脚本内容(data.sql)

--插入记录   
insert into test_table values(1,'Unmi');    

select *    
from test_table   
where id>0;   
--and name like '%Unmi' ;   

--删除 ID 为 1 的记录   
delete  from test_table where id=1;  
--插入记录 
insert into test_table values(1,'Unmi'); 
select * 
from test_table 
where id>0; 
--and name like '%Unmi' ; 
--删除 ID 为 1 的记录 
delete  from test_table where id=1; 
ant 执行后控制台输出为: 
sql: 
[sql] Executing resource: E:\Workspace\Eclipse\TestAnt\src\data.sql 
[sql] 3 of 3 SQL statements executed successfully 
sql_out.text 中的输出内容是: 
1 rows affected 
ID,NAME 
1,Unmi 
0 rows affected 
1 rows affected 



不过ANT执行的SQL语句不支持行末的注释符 "--",这有待改进。 

2、Java代码调用ANT的SQLExec执行脚本文件 


package com.unmi;   

import java.io.*;   

import org.apache.tools.ant.*;   
import org.apache.tools.ant.taskdefs.*;   
import org.apache.tools.ant.types.*;   

/**  
* 调用 ant.jar 的 SQLExec 执行 SQL 脚本文件  
* @author Unmi  
*/  
public class AntExecSql {   

/**  
* @param args  
*/  
public static void main(String[] args) {   
SQLExec sqlExec = new SQLExec();   

//设置数据库参数   
sqlExec.setDriver("oracle.jdbc.driver.OracleDriver");   
sqlExec.setUrl("jdbc:oracle:thin:@10.128.x.x:1521:xxsid");   
sqlExec.setUserid("xxuser");   
sqlExec.setPassword("xxpass");   

//要执行的脚本   
sqlExec.setSrc(new File("src/data.sql"));   

//有出错的语句该如何处理   
sqlExec.setOnerror((SQLExec.OnError)(EnumeratedAttribute.getInstance(   
SQLExec.OnError.class, "abort")));   

sqlExec.setPrint(true); //设置是否输出   

//输出到文件 sql.out 中;不设置该属性,默认输出到控制台   
sqlExec.setOutput(new File("src/sql.out"));   
sqlExec.setProject(new Project()); // 要指定这个属性,不然会出错   
sqlExec.execute();   
}   
}  
package com.unmi; 
import java.io.*; 
import org.apache.tools.ant.*; 
import org.apache.tools.ant.taskdefs.*; 
import org.apache.tools.ant.types.*; 
/** 
* 调用 ant.jar 的 SQLExec 执行 SQL 脚本文件 
* @author Unmi 
*/ 
public class AntExecSql { 
/** 
* @param args 
*/ 
public static void main(String[] args) { 
SQLExec sqlExec = new SQLExec(); 

//设置数据库参数 
sqlExec.setDriver("oracle.jdbc.driver.OracleDriver"); 
sqlExec.setUrl("jdbc:oracle:thin:@10.128.x.x:1521:xxsid"); 
sqlExec.setUserid("xxuser"); 
sqlExec.setPassword("xxpass"); 

//要执行的脚本 
sqlExec.setSrc(new File("src/data.sql")); 

//有出错的语句该如何处理 
sqlExec.setOnerror((SQLExec.OnError)(EnumeratedAttribute.getInstance( 
SQLExec.OnError.class, "abort"))); 

sqlExec.setPrint(true); //设置是否输出 

//输出到文件 sql.out 中;不设置该属性,默认输出到控制台 
sqlExec.setOutput(new File("src/sql.out")); 
sqlExec.setProject(new Project()); // 要指定这个属性,不然会出错 
sqlExec.execute(); 
} 
} 



项目中需要引入ant.jar,并且在代码中需执行sqlExec.setProject(new Project()); 无意义的操作。其他用法及效果与前面类似。 

3、从ant.jar中抽离出需要的类SQLExec和JDBCTask 

使用代码如下(AntSqlExec.java): 


package com.unmi.sql;   

import java.io.*;   

/**  
* Java 执行 Sql 脚本文件  
* @author Unmi  
*/  
public class AntSqlExec {   

/**  
* @param args  
* @throws Exception   
*/  
public static void main(String[] args) throws Exception {   
SQLExec sqlExec = new SQLExec();   

//设置数据库参数   
sqlExec.setDriver("oracle.jdbc.driver.OracleDriver");   
sqlExec.setUrl("jdbc:oracle:thin:@10.128.x.x:1521:xsid");   
sqlExec.setUserid("xxuser");   
sqlExec.setPassword("xxpass");   

//要执行的脚本   
sqlExec.setSrc(new File("src/data.sql"));   

//有出错的语句该如何处理   
sqlExec.setOnerror(SQLExec.ON_ERROR_ABORT); //abort/conitue/stop   

sqlExec.setPrint(true); //设置是否输出   

//输出到文件 sql.out 中;不设置该属性,默认输出到控制台   
sqlExec.setOutput(new File("src/sql.out"));    
sqlExec.execute();   
}   
}  
package com.unmi.sql; 
import java.io.*; 
/** 
* Java 执行 Sql 脚本文件 
* @author Unmi 
*/ 
public class AntSqlExec { 
/** 
* @param args 
* @throws Exception 
*/ 
public static void main(String[] args) throws Exception { 
SQLExec sqlExec = new SQLExec(); 

//设置数据库参数 
sqlExec.setDriver("oracle.jdbc.driver.OracleDriver"); 
sqlExec.setUrl("jdbc:oracle:thin:@10.128.x.x:1521:xsid"); 
sqlExec.setUserid("xxuser"); 
sqlExec.setPassword("xxpass"); 

//要执行的脚本 
sqlExec.setSrc(new File("src/data.sql")); 

//有出错的语句该如何处理 
sqlExec.setOnerror(SQLExec.ON_ERROR_ABORT); //abort/conitue/stop 

sqlExec.setPrint(true); //设置是否输出 

//输出到文件 sql.out 中;不设置该属性,默认输出到控制台 
sqlExec.setOutput(new File("src/sql.out")); 
sqlExec.execute(); 
} 
}




因SQLExec.java 和JDBCTask.java 代码行较多,不便列出,可下载SQLExec(FromAnt).rar 解开来看。抽取出来的类修改后不再依赖于ANT的Jar 包了(不再需要 引入 org.apache.* 包了),并简化的代码,削去了一些不用的功能,如设置是否是非关系型数据库、设置数据库版本、扩展属性的设置、设置classpath 属性通过自定义类加载器加载驱动等。前面说过,还有点遗憾的是还不支持行末的注释符 "--" 或 "//",还需增强,所以目前使用。

前面讲的大体都是在执行SQL脚本的功能,其实SQLExec 的还提供事物控制的功能。比如autoCommit属性的设置,可同时调入多个SQL脚本文件,让多个SQL脚本同处一个事物当中,更为细致的用法还有待您来发掘,在修改后的 SQLExec.java和JDBCTask.java实用功能都有保留。