HSQLDB是一个开源的纯Java嵌入式关系数据库管理系统,小巧方便,具有标准的SQL语法和Java接口,可以作为内存数据库、独立数据库和C/S数据库,支持索引、事务处理、Java存储过程、完整性引用和约束等功能。
本章介绍Eclipse环境下的HSQLDB数据库应用开发,包括HSQLDB数据库的安装和配置、SqlExplorer数据库插件的安装和配置、常见数据库操作的封装,最后通过学生成绩管理系统介绍了基于HSQLDB进行数据库应用开发的具体步骤。
5.1 HSQLDB数据库的使用
5.1.1 下载并安装HSQLDB数据库
在使用HSQLDB数据库之前,本小节首先介绍HSQLDB数据库的下载和安装。与大多数Java应用程序一样,只需解压缩安装包即可完成HSQLDB数据库的安装。
跟我做
(1)登录HSQLDB的官方网站http://www.hsqldb.org,下载HSQLDB数据库的安装包hsqldb_1_8_0_x.zip。
(2)将下载的安装包解压缩到设定的安装目录,如d:/hsqldb。
(3)将D:/hsqldb/lib目录下的hsqldb.jar文件加入到CLASSPATH环境变量中,HSQLDB安装完毕。安装后其目录结构如图5-1所示。
图5-1 HSQLDB数据库的目录结构
%注意:设置CLASSPATH环境变量的方法参见1.1节,所有的HSQLDB组件如数据库引擎、服务器进程、JDBC驱动程序、文档以及一些实用工具都放在hsqldb.jar文件中。
5.1.2 使用Memory模式运行HSQLDB
下面介绍HSQLDB的几种运行模式。
● 独立服务器模式:类似于其他关系数据库的标准客户机/服务器数据库配置,允许出现使用TCP 套接字的并发连接。
● 独立Web服务器模式:作为Web服务器通过HTTP接受SQL查询,也能作为任何标准Web容器中的Servlet来运行。由于HTTP是无状态的,所以本模式中不存在事务。
● 单机模式:是许多嵌入式应用程序的首选模式,该模式下应用程序使用JDBC创建一个数据库连接,HSQLDB引擎也运行在该应用程序中。
● Memory模式:所有数据库表和索引都放在内存中,数据不进行外存储,没有持
久性。
本小节将以Memory模式为例,介绍如何基于HSQLDB数据库进行应用的开发。
跟我做
(1)启动Eclipse,创建名字为hsqldbdemo的Java工程,并创建Java类MemoryDB.java。
%注意:切记将hsqldb.jar加到工程的构建路径上。
(2)编辑MemoryDB.java文件。输入如下代码:
try {
//加载HSQLDB数据库JDBC驱动
Class.forName("org.hsqldb.jdbcDriver");
//在内存中建立临时数据库score,用户名为sa,密码为空
Connection connect = DriverManager.getConnection("jdbc:hsqldb:mem:score",
"sa", "");
System.out.println(“在此行上设置一个断点”);
} catch (SQLException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
在内存中建立临时数据库“score”,用户名为“sa”,密码为空。上述程序片断是典型的通过JDBC连接数据库的方法,其中数据库URL“jdbc:hsqldb:mem:score”中的“mem”部分定义了HSQLDB数据库工作在Memory模式下。一旦跟数据库的连接建立后,数据库引擎就启动起来了,接下来即可创建Table表。
5.2 使用SQLExplorer插件连接数据库
SQLExplorer插件可以通过JDBC访问常用的关系数据库,同时也支持像Hibernate这样的工具访问数据库。其官方站点为http://sourceforge.net/projects/eclipsesql。
本节介绍如何使用SQLExplorer插件,查看5.1.2小节建立的score内存数据库的具体内容。首先介绍SQLExplorer插件的安装,然后介绍SQLExplorer插件的具体使用方法。
工作在内存模式下的HSQLDB数据库,会随着程序的退出而关闭,所以在下面的操作中MemoryDB要始终保持运行状态。本章在程序中设置断点,调试运行,使程序保持运行状态。
跟我做
(1)打开MemoryDB.java文件,在程序行“System.out.println(“在此行上设置一个断点”);”前设置一个断点。
(2)右击“MemoryDB.java”文件,在快捷菜单中选择【调试方式】|【Java应用程序】命令,MemoryDB.java程序调试运行至断点处,建立了内存数据库score。
(3)单击【窗口】菜单,依次选择【打开透视图】|【其它…】命令,打开【选择透视图】对话框,选择“SQLExplorer”,打开SQLExplorer透视图,如图5-2所示。
图5-2 选择SQLExplorer透视图
SQLExplorer透视图有7项内容,分别如下:
● Aliases 别名,用来标识数据库连接串。
● Connection Info 连接信息,用来显示连接数据库时的相关信息,如数据库产品名称、版本、JDBC驱动程序的名称、版本、用户名、连接串、是否自动提交等。
● Connections 显示活动的连接情况。
● Database Structure View显示数据库结构。
● Drivers 配置驱动程序用。
● SQL History 执行SQL的历史记录。
● SQL Results 执行SQL的结果集。
(4)打开如图5-3所示的Drivers视图,右击“HSQLDB In-Memory”,在快捷菜单中选择【Change the selected Driver】命令,打开Modify Driver窗口。
(5)选择【Extra Class Path】选项卡,单击【Add】按钮,在【打开】窗口中选择d:/hsqldb/lib/hsqldb.jar,将HSQLDB数据库的驱动程序加入到classpath中。
(6)在【Example URL】文本框中输入“jdbc:hsqldb:mem:score”,单击【确定】按钮,如图5-4所示。这时,Drivers视图中的“HSQLDB In-Memory”由变成,表示HSQLDB数据库的驱动程序配置成功。
图5-3 Drivers视图 图5-4 配置数据库驱动
(7)打开SQLExplorer插件的Aliases别名视图,单击【创建】图标,打开【Create new Alias】对话框。
(8)在【Name】文本框中输入“hsqlMemoryDB”,选择HSQLDB In-Memory驱动,在【URL】文本框中输入“jdbc:hsqldb:mem:score”,在【User Name】文本框中输入“sa”,单击【确定】按钮,如图5-5所示。在Aliases别名视图中出现刚建立的“hsqlMemoryDB”连接。
(9)右击“hsqlMemoryDB”,在快捷菜单中选择【Open…】命令,弹出有关数据库连接的确认框,可以更改用户名与密码,也可以设置是否自动提交,这里保持所有的选项为默认值。
(10)单击【确定】按钮,在Database Structure View视图中即可看到Database,展开Database树形结构,如图5-6所示。
图5-5 创建数据库连接别名 图5-6 Database Structure View视图
5.3 创建Score成绩表
至此通过SQLExplorer插件已经建立了与HSQLDB数据库的连接。本节通过在SQLExplorer中编辑和运行SQL脚本建立Score表,为后续几节的数据库操作做准备。
5.3.1 编写脚本
跟我做
(1)打开SQLExplorer插件的Connections视图,其中显示当前数据库的连接情况,这里有一个活动的连接,如图5-7所示。
图5-7 Connections视图
(2)单击Connections视图中的按钮,选择【New SQL Editor】命令,创建一个新的SQL编辑器。
(3)在SQL编辑器中输入如下SQL语句。
CREATE TABLE Score
(SNO CHAR(7) NOT NULL,
CNO CHAR(6) NOT NULL,
GRADE NUMERIC(4,1),
PRIMARY KEY(SNO,CNO));
该SQL语句在score内存数据库中创建一张名为Score的表。该表包括3个字段:学号(SNO)、课程编号(CNO)、课程分数(GRADE),并且以SNO、CNO两个字段作为主键。
5.3.2 在SQLExplorer中运行脚本
SQL Editor是SQLExplorer插件提供的功能强大、使用方便的SQL语句编辑器,如
图5-8所示。SQL Editor提供编辑SQL语句,选中并执行部分SQL语句,打开和保存SQL脚本文件等功能。本小节介绍如何在SQLExplorer中运行SQL语句。
图5-8 SQL Editor
跟我做
(1)单击【Execute SQL】按钮,执行所输入的SQL语句。
%注意:如果SQL Editor中存在多条SQL语句,首先选中想要执行的语句,然后单击【Execute SQL】按钮,如图5-9所示。
(2)从打开SQLExplorer插件的Database Structure View视图中可以看到刚才创建的表格。选中该表,可以看到该表的详细结构,如图5-10所示。
图5-9 执行多条SQL语句中的某一条 图5-10 新创建的Score表
(3)打开SQLExplorer插件的SQL History视图,可以看到执行过的所有SQL语句列表,如图5-11所示。
图5-11 SQL History视图
5.4 使用JavaBean映射成绩表
对象关系映射(ORM)是一种为了解决面向对象与关系数据库存在的互不匹配的现象的技术。其本质就是将数据从关系数据库的二维表格形式改换一种形式,以更加容易理解的面向对象形式来表现具有某种关系的数据。本节将遵循ORM的思想,以Score表为例说明如何以JavaBean的方式来映射HSQLDB数据库中的Score表。
5.4.1 实现Score类
表Score共包括3个字段:SNO(学号)、CNO(课程编号)、GRADE(分数)。下面创建一个JavaBean来映射这个表。
跟我做
(1)右击“hsqldbdemo”工程的“src”源文件夹,在快捷菜单中选择【新建】|【包】命令,打开【新建Java包】窗口。
(2)在【名称】文本框中输入“hsqldb.javabean”,单击【完成】按钮,建立名为“hsqldb.javabean”的package。
(3)在包“hsqldb.javabean”中创建Java类Score.java。
(4)编辑Score.java文件,输入如下代码:
package hsqldb.javabean;
//映射HSQLDB数据库Score表的JavaBean类
public class Score {
// 学号
private String SNO;
// 课程编号
private String CNO;
// 课程分数
private float GRADE;
}
Score类为标准的JavaBean,为Score类声明了3个属性:SNO、CNO、GRADE,分别表示学号、课程编号和课程分数。
5.4.2 添加getter/setter方法
为了能够实现查询、修改等数据库常见操作,需要为Score类加入getter/setter方法。
跟我做
(1)打开Score.java文件,右击文件中的任何空白区域,在快捷菜单中选择【源代码】|【生成Getter和Setter】命令,打开【生成Getter和Setter】窗口,如图5-12所示。
(2)单击【全部选中】按钮,全部选中3个属性,单击【确定】按钮。生成完整Score类代码如下:
package hsqldb.javabean;
//映射Score表的Javabean类
public class Score {
// 学号
private String SNO;
// 课程编号
private String CNO;
// 课程分数
private float GRADE;
//CNO属性的getter方法
public String getCNO() {
return CNO;
}
//CNO属性的setter方法
public void setCNO(String cno) {
CNO = cno;
}
//GRADE属性的getter方法
public float getGRADE() {
return GRADE;
}
//GRADE属性的setter方法
public void setGRADE(float grade) {
GRADE = grade;
}
//SNO属性的getter方法
public String getSNO() {
return SNO;
}
//SNO属性的setter方法
public void setSNO(String sno) {
SNO = sno;
}
}
图5-12 【生成Getter和Setter】窗口
为Score类的3个属性添加Getter/Setter方法。Score类为标准的JavaBean。
5.5 使用ScoreDAO管理成绩
DAO是数据访问接口Data Access Object的简称,在业务逻辑与数据库资源之间。DAO是一种常用的设计模式,可以用来封装数据库的驱动、数据库URL、用户名和密码。以后要更改数据库的类型,如把MSSQL换成Oracle,则只需要更改DAOFactory里面的相关信息即可。另外,DAO把对数据库的操作如最基本的查询、更新、删除和插入全部封装在里面,如加入一个学生一门课的成绩,只要调用DAO中的insertScore(Score score)方法即可,省去了编写复杂的SQL语句的麻烦,使得操作数据库的动作更加方便。
跟我做
(1)建立ScoreDAOFactory类。通过该工厂类建立了和数据库的连接,可以关闭与数据库的连接,另外通过该工厂类可以取得一个ScoreDAO的实例。代码如下:
package hsqldb.dbo;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
//创建ScoreDAO类的工厂类
public class ScoreDAOFactory {
//HSQLDB数据库的Driver名称
public static final String DRIVER = "org.hsqldb.jdbcDriver";
//将建立的内存数据库的URL
public static final String URL = "jdbc:hsqldb:mem:score";
//Connection对象,表示到数据库的连接
private static Connection connection = null;
/**
* 建立到内存数据库的连接
* @return
*/
public static Connection createConnection() {
if (connection == null) {
try {
//加载数据库驱动程序
Class.forName(DRIVER);
//建立到数据库的连接
connection = DriverManager.getConnection(URL, "sa", "");
} catch (SQLException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
return connection;
}
/**
* 释放到内存数据库的连接
*/
public static void closeConnection() {
if (connection != null)
try {
//释放到数据库的连接
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
/**
* 取得一个ScoreDAO的实例
* @return
*/
public static ScoreDAO getScoreDAO() {
return new ScoreDAO();
}
}
该类为ScoreDAO的工厂类,用来取得一个ScoreDAO的实例。
(2)建立ScoreDAO类,封装常见的数据库操作。编写代码如下:
package hsqldb.dbo;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import hsqldb.javabean.Score;
//ScoreDAO类,用来封装对数据库的常见操作
public class ScoreDAO {
// 数据库的JDBC连接
private Connection connection;
// Statement对象
private Statement statement;
// 需要执行的SQL语句
private String sql;
/**
* 构造函数,建立到score数据库的连接,同时在score数据库中建立Score表
*/
public ScoreDAO() {
// 建立到score数据库的连接
connection = ScoreDAOFactory.createConnection();
try {
//创建statement对象
statement = connection.createStatement();
//创建Score表的SQL语句
sql = "CREATE TABLE Score (SNO CHAR(7) NOT NULL,CNO CHAR(6) NOT NULL,GRADE NUMERIC(4,1),PRIMARY KEY(SNO,CNO))";
//执行SQL语句
statement.execute(sql);
} catch (SQLException e) {
e.printStackTrace();
}
}
}
首先取得数据库的连接,然后执行“CREATE TABLE”SQL语句,创建Score表。该表具有3个字段:学号、课程编号和分数。
5.5.1 添加InsertScore方法增加成绩
“INSERT INTO”语句用来向数据库中插入新的记录。为了简化插入记录操作,完全以面向对象的方式实现对数据库的插入操作,本小节介绍如何对插入语句进行封装。
跟我做
封装INSERT INTO标准SQL语句。编写代码如下:
/**
* 将Score的一个对象插入到数据库中
*
* @param score
*/
public void insertScore(Score score) {
//将参数score类的各个属性拼接成插入记录的SQL语句
sql = "INSERT INTO SCORE VALUES(" + "/'" + score.getSNO() + "/',"
+ "/'" + score.getCNO() + "/'," + score.getGRADE() + ")";
try {
//程序INSERT INTO 语句为Score类插入一条记录,记录的三个字段值对应着score类的三个属性
statement.execute(sql);
} catch (SQLException e) {
e.printStackTrace();
}
}
将Score类的属性拼接成INSERT语句,这样进行数据库的插入操作只需传入一个Score类的实例,完全以面向对象的方式往数据库中插入记录。
5.5.2 添加SelectScore方法查询成绩
查询操作是数据库的常见操作,这里通过对SELECT SQL语句的封装实现对指定记录的查询以及遍历查询两个方法。
跟我做
(1)对指定记录的查询。在建立表格Score时,指定了以SNO和CNO作为该表的主键。该方法实现了查询SNO和CNO字段值与给定Score对象SNO和CNO属性值相同的记录。代码如下:
/**
* 在数据库中查询包含某个Score对象信息的记录
*
* @param score
* @return
*/
public ResultSet selectScore(Score score) {
//查询后的结果集
ResultSet result = null;
//将参数Score类的各个属性拼接成查询记录的SQL语句
sql = "select * from score where SNO=" + score.getSNO() + "and CNO="
+ score.getCNO();
try {
//执行查询,返回与Score类的SNO、CNO属性值相同的记录
result = statement.executeQuery(sql);
} catch (SQLException e) {
e.printStackTrace();
}
return result;
}
(2)对所有记录的查询。为了更加方便地查询数据库目前记录情况,这里实现了简单返回所有记录的遍历查询。编写代码如下:
/**
* 查询数据库中的所有记录
*
* @return
*/
public ResultSet selectAll() {
//查询后的结果集
ResultSet result = null;
//查询所有记录的SQL语句
sql = "select * from score";
try {
//执行查询,返回所有的记录
result = statement.executeQuery(sql);
} catch (SQLException e) {
e.printStackTrace();
}
return result;
}
5.5.3 添加DeleteScore方法删除成绩
“DELETE”语句用来从数据库中删除记录。为了简化删除记录操作,完全以面向对象的方式实现对数据库的删除操作,本小节介绍如何对DELETE语句进行封装。
跟我做
封装DELETE SQL语句,删除数据库中SNO和CNO字段值与指定的Score对象的SNO、CNO值相同的记录。编写代码如下:
/**
* 删除某个数据库记录
*
* @param score
*/
public void deleteScore(Score score) {
//将参数Score类的各个属性拼接成删除记录的SQL语句
sql = "delete from score where SNO=" + score.getSNO() + "and CNO="
+ score.getCNO();
try {
//执行删除操作的SQL语句
statement.execute(sql);
} catch (SQLException e) {
e.printStackTrace();
}
}
5.5.4 添加UpdateScore方法修改成绩
“UPDATE”语句用来更新数据库中的某条记录。为了简化更新操作,完全以面向对象的方式实现对数据库的更新,本小节介绍如何对UPDATE语句进行封装。
跟我做
封装UPDATE SQL语句将数据库中某条记录更新为指定的Score类的SNO、CNO和GRADE值。编写代码如下:
/**
* 更新数据库中的某条记录
*
* @param oldScore
* @param newScore
*/
public void updateScore(Score oldScore, Score newScore) {
//将数据库中满足条件的记录更新为newScore类的SNO、CNO和GRADE属性值
sql = "update score set SNO=" + newScore.getSNO() + ",CNO="
+ newScore.getCNO() + ",GRADE=" + newScore.getGRADE()
+ " where SNO=" + oldScore.getSNO() + "and CNO="
+ oldScore.getCNO();
try {
//执行数据库更新语句
statement.executeUpdate(sql);
} catch (SQLException e) {
e.printStackTrace();
}
}
5.6 编写测试客户端
采用DAO模式的目的就在于简化对数据库的操作。本节将以一个操作数据库的实例来说明以DAO方式访问数据库的具体步骤,从而深刻体会DAO模式的实用性。
跟我做
(1)通过ScoreDAOFactory取得一个ScoreDAO的实例,同时在内存中创建了score数据库,并且建立了具有3个字段的Score表。
(2)准备3个Score类的对象,分别为firstScore、secondScore和thirdScore。编写代码如下:
//firstScore 实例,
Score firstScore = new Score();
//CNO字段值为34
firstScore.setCNO("34");
//SNO字段值为1
firstScore.setSNO("1");
//GRADE字段值为2.5
firstScore.setGRADE((float) 2.5);
// secondScore实例
Score secondScore = new Score();
//CNO字段值为45
secondScore.setCNO("45");
//GRADE字段值为67.9
secondScore.setGRADE((float) 67.9);
//SNO字段值为2
secondScore.setSNO("2");
// thirdScore实例
Score thirdScore = new Score();
//CNO字段值为78
thirdScore.setCNO("78");
//SNO字段值为3
thirdScore.setSNO("3");
//GRADE字段值为89
thirdScore.setGRADE((float) 89.0);
(3)将firstScore插入到数据库中。编写代码如下:
// 通过ScoreDAO的实例执行插入操作
scoreDAO.insertScore(firstScore);
// 查询数据库中的所有记录
result = scoreDAO.selectAll();
// 输出所有记录信息
info(result);
运行结果如图5-13所示。
图5-13 插入firstScore记录的执行结果
(4)将secondScore插入到数据库中。编写代码如下:
// 通过ScoreDAO的实例执行插入操作
scoreDAO.insertScore(secondScore);
// 查询数据库中的所有记录
result = scoreDAO.selectAll();
// 输出所有记录信息
info(result);
运行结果如图5-14所示。
图5-14 插入secondScore记录的执行结果
(5)将secondScore记录修改为thirdScore。编写代码如下:
//通过ScoreDAO的实例执行更新操作
scoreDAO.updateScore(secondScore, thirdScore);
//查询数据库中的所有记录
result = scoreDAO.selectAll();
//输出记录信息
info(result);
运行结果如图5-15所示。
图5-15 更新secondScore后的执行结果
(6)将firstScore记录删除。编写代码如下:
//通过ScoreDAO的实例执行删除操作
scoreDAO.deleteScore(firstScore);
//查询数据库中的所有记录
result = scoreDAO.selectAll();
//输出记录信息
info(result);
运行结果如图5-16所示。
图5-16 删除firstScore后的执行结果
以上简单的实例实现了数据库的查询、插入、删除和更新操作。整个操作完全以面向对象的形式进行,屏蔽了复杂的SQL语句,提高了程序的可读性和开发效率。