可重用的 Hsqldb 启动、停止之 Ant 任务脚手架
立正。。。
稍息
讲一下
坐下。。。
在Eclipse里用Ant来启动Hsqldb
<!-- Start the Hsqldb database server -->
<target
name=
"dbstart"
description=
"Start the Hsqldb database server"
>
<java
classname=
"org.hsqldb.Server"
fork=
"yes"
classpathref=
"hsqldb.classpath"
failonerror=
"true"
>
<arg
value=
"-database.0"
/>
<arg
value=
"file:${database.dir}/db"
/>
</java>
</target>
此时如果要停止 Hsqldb ,即点击红色按钮来 Terminate 掉它,实现上,Hsqldb的Java线程还是在后台运行的,它并没有真正结束。
判断的方法有四种:
1、再次运行 ant startdb 任务,会发现 db.lck 还被使用,而 <delete dir="${database.dir}"/> 删除不了,被前一个实例 Lock 住了。
Buildfile: xxx/build.xml
startdb:
[delete] Deleting directory xxx/database
BUILD FAILED
xxx/build.xml:88: Unable to delete file xxx/database/db.lck
2、利用JDK 5.0以上的版本中的 jps 来查看,即:
%JAVA_HOME%/bin/jps -lvm
你可以看到其中有如下的信息显示
<pid> org.hsqldb.Server -database.0 file:database/db
即表明它还是在运行当中。
3、netstat -a | find "9001"
TCP XXX:9001 XXX:0 LISTENING
发现 Hsqldb 默认的服务端口 9001 还在监听中。
4、再次运行你的数据库连接程序,程序运行正常,还是可以连接上去,并可以完全正常进行你的数据操作。
由上面的方法可见它还是在正常运行中,Eclipse里的红色按钮并没有真正 Terminate 掉它。
那如何真正停止掉它呢?同样也有几种方法。
1、利用 Ant 本身提供的 sql 任务,如下发送 SHUTDOWN [COMPACT|IMMEDIATELY] 命令过去就可以了,如下:
<!-- Shutdown the Hsqldb database server via Ant sql Task -->
<target
name=
"dbshutdown"
description=
"Shutdown the Hsqldb database server via Ant sql Task"
>
<echo
message=
"Ignore the message:'java.sql.SQLException: Connection is broken: java.io.EOFException', Don't care about it."
/>
<sql
driver=
"org.hsqldb.jdbcDriver"
url=
"jdbc:hsqldb:hsql://localhost/"
userid=
"sa"
password=
""
classpathref=
"hsqldb.classpath"
onerror=
"stop"
print=
"true"
>
<![CDATA[
shutdown;
]]></sql>
</target>
但是虽然这个可以让 Hsqldb Server 停止掉了,但是会报错误,build出现错误我是不能接受的,不知道你是否接受?
shutdowndb:
[echo] Ignore the message:'java.sql.SQLException: Connection is broken: java.io.EOFException', Don't care about it.
[sql] Executing commands
[sql] 0 rows affected
BUILD FAILED
xxx/build.xml:124: java.sql.SQLException: Connection is broken: java.io.EOFException
打开 verbose 选项看一看更加详细的信息:
shutdowndb:
[echo] Ignore the message:'java.sql.SQLException: Connection is broken: java.io.EOFException', Don't care about it.
[sql] connecting to jdbc:hsqldb:hsql://localhost/
[sql] Loading org.hsqldb.jdbcDriver using AntClassLoader with classpath xxx/lib/hsqldb.jar
BUILD FAILED
java.sql.SQLException: socket creation error
at org.apache.tools.ant.taskdefs.JDBCTask.getConnection(JDBCTask.java:314)
at org.apache.tools.ant.taskdefs.SQLExec.execute(SQLExec.java:346)
at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:275)
at org.apache.tools.ant.Task.perform(Task.java:364)
at org.apache.tools.ant.Target.execute(Target.java:341)
at org.apache.tools.ant.Target.performTasks(Target.java:369)
at org.apache.tools.ant.Project.executeSortedTargets(Project.java:1216)
at org.apache.tools.ant.Project.executeTarget(Project.java:1185)
at org.apache.tools.ant.helper.DefaultExecutor.executeTargets(DefaultExecutor.java:40)
at org.apache.tools.ant.Project.executeTargets(Project.java:1068)
at org.apache.tools.ant.Main.runBuild(Main.java:668)
at org.apache.tools.ant.Main.startAnt(Main.java:187)
at org.apache.tools.ant.launch.Launcher.run(Launcher.java:246)
at org.apache.tools.ant.launch.Launcher.main(Launcher.java:67)
Caused by: java.sql.SQLException: socket creation error
at org.hsqldb.jdbc.Util.sqlException(Unknown Source)
at org.hsqldb.jdbc.jdbcConnection.<init>(Unknown Source)
at org.hsqldb.jdbcDriver.getConnection(Unknown Source)
at org.hsqldb.jdbcDriver.connect(Unknown Source)
at org.apache.tools.ant.taskdefs.JDBCTask.getConnection(JDBCTask.java:304)
... 13 more
--- Nested Exception ---
java.sql.SQLException: socket creation error
at org.hsqldb.jdbc.Util.sqlException(Unknown Source)
at org.hsqldb.jdbc.jdbcConnection.<init>(Unknown Source)
at org.hsqldb.jdbcDriver.getConnection(Unknown Source)
at org.hsqldb.jdbcDriver.connect(Unknown Source)
at org.apache.tools.ant.taskdefs.JDBCTask.getConnection(JDBCTask.java:304)
at org.apache.tools.ant.taskdefs.SQLExec.execute(SQLExec.java:346)
at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:275)
at org.apache.tools.ant.Task.perform(Task.java:364)
at org.apache.tools.ant.Target.execute(Target.java:341)
at org.apache.tools.ant.Target.performTasks(Target.java:369)
at org.apache.tools.ant.Project.executeSortedTargets(Project.java:1216)
at org.apache.tools.ant.Project.executeTarget(Project.java:1185)
at org.apache.tools.ant.helper.DefaultExecutor.executeTargets(DefaultExecutor.java:40)
at org.apache.tools.ant.Project.executeTargets(Project.java:1068)
at org.apache.tools.ant.Main.runBuild(Main.java:668)
at org.apache.tools.ant.Main.startAnt(Main.java:187)
at org.apache.tools.ant.launch.Launcher.run(Launcher.java:246)
at org.apache.tools.ant.launch.Launcher.main(Launcher.java:67)
也就是说在执行 SHUTDOWN 命令后,
org.apache.tools.ant.taskdefs.JDBCTask.getConnection(JDBCTask.java:314) 还去 getConnection,那肯定就出错了。
2、自己写个简单的 Ant 脚本来关闭它
ShutdownTask.java
import
java.sql.Connection;
import
java.sql.DriverManager;
import
java.sql.SQLException;
import
java.sql.Statement;
import
org.apache.tools.ant.BuildException;
import
org.apache.tools.ant.Task;
/**
*
ShutdownTask:
Ant
Task
for
shutdown
the
Hsqldb
server.
*
*
@author
YuLimin
*/
public
class
ShutdownTask
extends
Task
{
// Defaut Value
private
String
msg
=
"ShutdownTask"
;
private
String
driver
=
"org.hsqldb.jdbcDriver"
;
private
String
url
=
"jdbc:hsqldb:hsql://localhost/"
;
private
String
userid
=
"sa"
;
private
String
password
=
""
;
private
String
sqlCommand
=
"SHUTDOWN"
;
public
ShutdownTask()
{
super
();
}
/**
*
For
Test
*
*
@param
argv
*
@throws
Exception
*/
public
static
void
main(
final
String[] argv)
{
final
ShutdownTask shutdownTask =
new
ShutdownTask();
shutdownTask.shutdown();
}
/**
*
The
method
executing
the
task
*/
public
void
execute()
throws
BuildException
{
System.
out
.println(
msg
+
" Begin......"
);
System.
out
.println(
"Driver="
+ getDriver());
System.
out
.println(
"URL="
+ getUrl());
System.
out
.println(
"Userid="
+ getUserid());
System.
out
.println(
"Password="
+ getPassword());
System.
out
.println(
"SqlCommand="
+ getSqlCommand());
shutdown();
System.
out
.println(
msg
+
" End......"
);
System.
out
.println();
}
/**
*
Shutdown
the
database
*/
public
void
shutdown()
{
Connection connection =
null
;
Statement statement =
null
;
try
{
Class.forName(getDriver());
connection = DriverManager.getConnection(getUrl(),getUserid(),getPassword());
statement = connection.createStatement();
statement.execute(getSqlCommand());
statement.close();
connection.close();
}
catch
(Exception e)
{
e.printStackTrace();
throw
new
RuntimeException(e);
}
finally
{
if
(statement !=
null
)
{
try
{
statement.close();
}
catch
(SQLException e)
{
throw
new
RuntimeException(e);
}
}
if
(connection !=
null
)
{
try
{
connection.close();
}
catch
(SQLException e)
{
throw
new
RuntimeException(e);
}
}
}
}
// More accessor method : setter & getter
public
void
setMsg(
final
String msg)
{
this
.
msg
= msg;
}
public
void
setDriver(
final
String driver)
{
this
.
driver
= driver;
}
public
void
setPassword(
final
String password)
{
this
.
password
= password;
}
public
void
setUrl(
final
String url)
{
this
.
url
= url;
}
public
void
setUserid(
final
String userid)
{
this
.
userid
= userid;
}
public
void
setSqlCommand(
final
String sqlCommand)
{
this
.
sqlCommand
= sqlCommand;
}
public
String getDriver()
{
return
driver
;
}
public
String getPassword()
{
return
password
;
}
public
String getUrl()
{
return
url
;
}
public
String getUserid()
{
return
userid
;
}
public
String getSqlCommand()
{
return
sqlCommand
;
}
public
String getMsg()
{
return
msg
;
}
}
编译 javac -classpath %ANT_HOME%/lib/ant.jar ShutdownTask.java
打包 jar cvf ShutdownTask.jar *.*
把 ShutdownTask.jar 直接放到项目的lib目录下,下面的示例 classpath 我直接引入到 hsqldb.classpath中,可以根据需要放到项目的不同地方再进行调整引入使用等等。。。:)
build.xml里的调用示例,爱怎么用就怎么用,提供好几个示例。
<!-- Classpath declaration -->
<path
id=
"hsqldb.classpath"
>
<fileset
dir=
"${lib.dir}"
>
<include
name=
"**/hsqldb.jar"
/>
<include
name=
"**/ShutdownTask.jar"
/>
</fileset>
</path>
<!-- Shutdown the Hsqldb database server via ShutdownTask -->
<target
name=
"dbshutdownTask"
description=
"Shutdown the Hsqldb database server via ShutdownTask"
>
<!-- Define ShutdownTask -->
<taskdef
name=
"shutdownTask"
classname=
"ShutdownTask"
classpathref=
"hsqldb.classpath"
/>
<!-- Call ShutdownTask -->
<!-- Default ShutdownTask, only like this -->
<!-- <shutdownTask/> -->
<!-- Sample MyShutdownTask -->
<!-- <shutdownTask driver="org.hsqldb.jdbcDriver" url="jdbc:hsqldb:hsql://localhost/" userid="sa" password="" sqlCommand="SHUTDOWN" msg="MyShutdownTask"/> -->
<!-- Sample MyShutdownTask SHUTDOWN COMPACT -->
<!-- <shutdownTask driver="org.hsqldb.jdbcDriver" url="jdbc:hsqldb:hsql://localhost/" userid="sa" password="" sqlCommand="SHUTDOWN COMPACT" msg="MyShutdownTask"/> -->
<!-- Sample MyShutdownTask SHUTDOWN IMMEDIATELY -->
<shutdownTask
driver=
"org.hsqldb.jdbcDriver"
url=
"jdbc:hsqldb:hsql://localhost/"
userid=
"sa"
password=
""
sqlCommand=
"SHUTDOWN IMMEDIATELY"
msg=
"MyShutdownTask"
/>
</target>
3、就在直接在命令行下运行 ant startdb ,然后 Ctrl + C 直接干掉它就可以。
如启动时的提示:From command line, use [Ctrl]+[C] to abort abruptly
补充
OS:Windows 2K Pro SP4 English
ant -version
Apache Ant version 1.6.5 compiled on June 2 2005
JDK 1.4.2 1.5.0 1.6.0 1.7.0都可以。。。
最后,如何使用它呢?
在其它项目中只要相应地 import 这个 build.xml 这个文件即可达到重用,如:新项目与这个项目并行,即
<?xml version="1.0" encoding="utf-8"?>
<project
name=
"JPA_OtherProject"
default=
"compile"
basedir=
"."
>
<import file="../Common/build.xml" />
......
也可以建立 build.properties 资源文件来配置一些信息等等。。。
附上完整的 build.xml 与 ShutdownTask.jar 以及 Eclipse项目文件,import 到 Eclipse 中,把 build.xml 拖到Ant视图里,直接就可以用了。
下载地址:
Hsqldb_Ant_Eclipse.rar
讲完了。
解散。。。