版权提醒
本系列文章为原创内容。转载请注明文章来源。
前言
本文中的配置方法仅使用了基础的 JDBC ,并未使用 JPA 或者 MyBatis 。
H2 数据库介绍
H2 是一个用 Java 开发的嵌入式数据库,它本身只有一个约 2.5 MB jar 文件,可以直接嵌入到应用项目中。
不需要安装数据库引擎,也不需要安装控制台应用程序,因为它的控制台基于浏览器。
虽然是轻量级嵌入式数据库,但功能齐全,支持自定义拓展,而且可以作为内存数据库使用。
导入 JDBC 驱动类
将 H2 数据库的 jar 文件复制到 WEB-INF/lib 文件夹中
通过 Listener 实现 H2 数据库随项目启动与关闭。
创建 Java 包以存放 DAO 层 Java 代码。
根据自己的情况写包名,这里我使用:com.chiyu.DAO
在包中创建新 Java 类 H2DBServerStartListener
package com.chiyu.DAO;
import org.h2.tools.Server;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
import java.sql.SQLException;
// 用于实现 H2 数据库随项目启动与关闭。
@WebListener
public class H2DBServerStartListener implements ServletContextListener {
//H2 数据库服务器实例。
private Server server;
// 服务器部署此 web 程序时,这段方法将被调用。
@Override
public void contextInitialized(ServletContextEvent sce) {
// 启动 H2 数据库。
try {
System.out.println("正在启动 H2 数据库...");
server = Server.createTcpServer().start();
System.out.println("H2 数据库启动成功!");
} catch (SQLException e){
System.out.println("H2 数据库启动出错。");
e.printStackTrace();
throw new RuntimeException(e);
}
}
// 服务器关闭此 web 程序时,这段方法将被调用。
@Override
public void contextDestroyed(ServletContextEvent sce) {
// 停止 H2 数据库。
if (this.server != null){
this.server.stop();
this.server = null;
}
}
}
在 web.xml 中配置 H2 数据库控制台的访问路径。在 标签之前,插入以下内容。
<servlet>
<servlet-name>H2Console</servlet-name>
<servlet-class>org.h2.server.web.WebServlet</servlet-class>
<init-param>
<param-name>webAllowOthers</param-name>
<param-value></param-value>
</init-param>
<init-param>
<param-name>trace</param-name>
<param-value></param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>H2Console</servlet-name>
<url-pattern>/Console/*</url-pattern>
</servlet-mapping>
启动 Tomcat ,测试 H2 数据库是否会正常随项目启动与关闭。
如果你的控制台 System.out.println() 输出内容为乱码,请参考本系列文章第二篇中的“解决项目在 Tomcat 中运行时,由 System.out.println() 输出的中文在 IDEA 控制台中乱码的问题”部分。
这部分可以参考官方文档Using Databases in Web Applications。
官方给出了一个自带的监听器用于启动数据库,但这个项目打算使用连接池模式使用数据库,所以这里不采用自带监听器。
现在访问 http://localhost:8088/SimpleBookstore/Console (根据自己设置的端口和路径来),测试能否进入 H2 数据库的控制台。
现在关闭 Tomcat 服务器,准备为项目添加新的数据库。
创建数据库
此项目的数据库结构如图
官方文档中说,如果 URL 指定的数据库不存在,则会创建一个新数据库,创建数据库的用户自动成为管理员。但 H2 数据库控制台不允许创建数据库,除非 Console 在启动期间或从系统托盘中的图标打开浏览器窗口,并且未启用远程访问。托盘图标的上下文菜单也可用于创建新数据库。
所以,我们关闭了 Tomcat 服务器,从下载的 H2 数据库压缩包 bin/h2.bat 启动数据库。
修改 url 中的数据库名
直接连接,就创建了我们想要的数据库
修改管理员密码
为了数据库安全,我们为管理员设置密码
ALTER USER sa SET PASSWORD '123456'
点击执行
创建需要的表
在 SQL 语句区填入以下内容并执行
CREATE TABLE book (
bid VARCHAR(13) PRIMARY KEY,
bname VARCHAR(30) NOT NULL,
price FLOAT NOT NULL,
author VARCHAR(30),
press VARCHAR(30)
);
CREATE TABLE customer (
cid VARCHAR(10) PRIMARY KEY,
cname VARCHAR(20) NOT NULL,
phone VARCHAR(20),
address VARCHAR(60)
);
CREATE TABLE border (
oid INT PRIMARY KEY,
cid VARCHAR(10) NOT NULL,
ostate VARCHAR(6) NOT NULL DEFAULT '未处理',
otime DATE NOT NULL,
receptor VARCHAR(20) NOT NULL,
address VARCHAR(60) NOT NULL,
phone VARCHAR(25),
FOREIGN KEY(cid) REFERENCES customer(cid)
);
CREATE TABLE borderitem (
oid INT NOT NULL,
bid VARCHAR(13) NOT NULL,
quantity int NOT NULL DEFAULT '1',
PRIMARY KEY(oid,bid),
FOREIGN KEY(oid) REFERENCES border(oid),
FOREIGN KEY(bid) REFERENCES book(bid)
);
点击左上角图标退出连接。关闭命令提示符窗口,关闭 H2 服务器。
配置连接池
H2 数据库官方文档中提到:对于H2来说,从内置的连接池中获得一个连接比使用DriverManager.getConnection()获得一个连接要快两倍。
使用本项目采用连接池模式使用 H2 数据库。
将 H2DBServerStartListener 类更改如下:
package com.chiyu.DAO;
import org.h2.jdbcx.JdbcConnectionPool;
import org.h2.tools.Server;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
import java.sql.SQLException;
// 用于实现 H2 数据库随项目启动与关闭。
@WebListener
public class H2DBServerStartListener implements ServletContextListener {
//H2 数据库服务器实例。
private Server server;
// H2 数据库连接池实例。
public JdbcConnectionPool cp;
// 服务器部署此 web 程序时,这段方法将被调用。
@Override
public void contextInitialized(ServletContextEvent sce) {
// 启动 H2 数据库。
try {
System.out.println("正在启动 H2 数据库...");
server = Server.createTcpServer().start();
System.out.println("H2 数据库启动成功!");
// 创建连接池。
cp = JdbcConnectionPool.create("jdbc:h2:~/Bookstore","sa","123456");
// 使用 ServletContext 存储连接池对象,以在全局使用。
sce.getServletContext().setAttribute("ConnectionPool", cp);
} catch (SQLException e){
System.out.println("H2 数据库启动出错。");
e.printStackTrace();
throw new RuntimeException(e);
}
}
// 服务器关闭此 web 程序时,这段方法将被调用。
@Override
public void contextDestroyed(ServletContextEvent sce) {
// 关闭未使用的池连接。
if (this.cp != null){
cp.dispose();
}
// 停止 H2 数据库。
if (this.server != null){
this.server.stop();
this.server = null;
}
}
}