H2数据库
H2数据库
H2作为一个嵌入型的数据库,它最大的好处就是可以嵌入到我们的Web应用中,和我们的Web应用绑定在一起,成为我们Web应用的一部分。下面来演示一下如何将H2数据库嵌入到我们的Web应用中。
二、在Java中操作H2数据库
2.1、以嵌入式(本地)连接方式连接H2数据库
这种连接方式默认情况下只允许有一个客户端连接到H2数据库,有客户端连接到H2数据库之后,此时数据库文件就会被锁定,那么其他客户端就无法再连接了。
连接语法:jdbc:h2:[file:][
例如:
jdbc:h2:~/test //连接位于用户目录下的test数据库
jdbc:h2:file:/data/sample
jdbc:h2:file:E:/H2/gacl(Windows only)
编写测试代码,如下:
1 /**
2 *
3 */
4 package jdbc.conn.h2.test;
5
6 import java.sql.Connection;
7 import java.sql.DriverManager;
8 import java.sql.ResultSet;
9 import java.sql.Statement;
10 import java.util.UUID;
11
12 /**
13 * <p>ClassName: H2ConnTest1<p>
14 * <p>Description: Java通过JDBC方式连接H2数据库<p>
15 * @author xudp
16 * @version 1.0 V
17 * @createTime 2014-12-18 上午11:22:12
18 */
19 public class H2ConnTest1 {
20 //数据库连接URL,当前连接的是E:/H2目录下的gacl数据库
21 private static final String JDBC_URL = "jdbc:h2:E:/H2/gacl";
22 //连接数据库时使用的用户名
23 private static final String USER = "gacl";
24 //连接数据库时使用的密码
25 private static final String PASSWORD = "123";
26 //连接H2数据库时使用的驱动类,org.h2.Driver这个类是由H2数据库自己提供的,在H2数据库的jar包中可以找到
27 private static final String DRIVER_CLASS="org.h2.Driver";
28
29 public static void main(String[] args) throws Exception {
30 // 加载H2数据库驱动
31 Class.forName(DRIVER_CLASS);
32 // 根据连接URL,用户名,密码获取数据库连接
33 Connection conn = DriverManager.getConnection(JDBC_URL, USER, PASSWORD);
34 Statement stmt = conn.createStatement();
35 //如果存在USER_INFO表就先删除USER_INFO表
36 stmt.execute("DROP TABLE IF EXISTS USER_INFO");
37 //创建USER_INFO表
38 stmt.execute("CREATE TABLE USER_INFO(id VARCHAR(36) PRIMARY KEY,name VARCHAR(100),sex VARCHAR(4))");
39 //新增
40 stmt.executeUpdate("INSERT INTO USER_INFO VALUES('" + UUID.randomUUID()+ "','大日如来','男')");
41 stmt.executeUpdate("INSERT INTO USER_INFO VALUES('" + UUID.randomUUID()+ "','青龙','男')");
42 stmt.executeUpdate("INSERT INTO USER_INFO VALUES('" + UUID.randomUUID()+ "','白虎','男')");
43 stmt.executeUpdate("INSERT INTO USER_INFO VALUES('" + UUID.randomUUID()+ "','朱雀','女')");
44 stmt.executeUpdate("INSERT INTO USER_INFO VALUES('" + UUID.randomUUID()+ "','玄武','男')");
45 stmt.executeUpdate("INSERT INTO USER_INFO VALUES('" + UUID.randomUUID()+ "','苍狼','男')");
46 //删除
47 stmt.executeUpdate("DELETE FROM USER_INFO WHERE name='大日如来'");
48 //修改
49 stmt.executeUpdate("UPDATE USER_INFO SET name='孤傲苍狼' WHERE name='苍狼'");
50 //查询
51 ResultSet rs = stmt.executeQuery("SELECT * FROM USER_INFO");
52 //遍历结果集
53 while (rs.next()) {
54 System.out.println(rs.getString("id") + "," + rs.getString("name")+ "," + rs.getString("sex"));
55 }
56 //释放资源
57 stmt.close();
58 //关闭连接
59 conn.close();
60 }
61 }
执行结果如下:
登录到H2控制台当中也可以看到创建好的USER_INFO表和表里面的数据,如下图所示:
这里需要说明一下使用这种"jdbc:h2:E:/H2/gacl"这种方式连接H2数据库容易遇到的问题,如果已经在H2的WebConsole控制台中登录gacl数据库,如下图所示:
此时gacl数据库就会被锁定,此时通过java代码连接gacl数据库时就会出现如下的错误,如所示:
1 Exception in thread "main" org.h2.jdbc.JdbcSQLException: Database may be already in use: "E:/H2/gacl.mv.db". Possible solutions: close all other connection(s); use the server mode [90020-183]
2 at org.h2.message.DbException.getJdbcSQLException(DbException.java:345)
3 at org.h2.message.DbException.get(DbException.java:168)
4 at org.h2.mvstore.db.MVTableEngine.init(MVTableEngine.java:108)
5 at org.h2.engine.Database.getPageStore(Database.java:2376)
6 at org.h2.engine.Database.open(Database.java:666)
7 at org.h2.engine.Database.openDatabase(Database.java:266)
8 at org.h2.engine.Database.<init>(Database.java:260)
9 at org.h2.engine.Engine.openSession(Engine.java:60)
10 at org.h2.engine.Engine.openSession(Engine.java:167)
11 at org.h2.engine.Engine.createSessionAndValidate(Engine.java:145)
12 at org.h2.engine.Engine.createSession(Engine.java:128)
13 at org.h2.engine.Engine.createSession(Engine.java:26)
14 at org.h2.engine.SessionRemote.connectEmbeddedOrServer(SessionRemote.java:347)
15 at org.h2.jdbc.JdbcConnection.<init>(JdbcConnection.java:108)
16 at org.h2.jdbc.JdbcConnection.<init>(JdbcConnection.java:92)
17 at org.h2.Driver.connect(Driver.java:72)
18 at java.sql.DriverManager.getConnection(DriverManager.java:571)
19 at java.sql.DriverManager.getConnection(DriverManager.java:215)
20 at jdbc.conn.h2.test.H2ConnTest1.main(H2ConnTest1.java:33)
21 Caused by: java.lang.IllegalStateException: The file is locked: nio:E:/H2/gacl.mv.db [1.4.183/7]
22 at org.h2.mvstore.DataUtils.newIllegalStateException(DataUtils.java:768)
23 at org.h2.mvstore.FileStore.open(FileStore.java:170)
24 at org.h2.mvstore.MVStore.<init>(MVStore.java:346)
25 at org.h2.mvstore.MVStore$Builder.open(MVStore.java:2754)
26 at org.h2.mvstore.db.MVTableEngine$Store.<init>(MVTableEngine.java:162)
27 at org.h2.mvstore.db.MVTableEngine.init(MVTableEngine.java:98)
28 ... 16 more
引起这个错误的原因是因为gacl数据库对应的文件已经被锁定了,所以java代码这边无法再访问,为了能够让Java代码能够正常访问,必须把WebConsole控制台那边的连接先断开,
断开数据库连接之后,Java代码这边就可以连接上去了。
2.2、使用TCP/IP的服务器模式(远程连接)方式连接H2数据库(推荐)
这种连接方式就和其他数据库类似了,是基于Service的形式进行连接的,因此允许多个客户端同时连接到H2数据库
连接语法:jdbc:h2:tcp://
范例:jdbc:h2:tcp://localhost/~/test
测试代码如下:
1 /**
2 *
3 */
4 package jdbc.conn.h2.test;
5
6 import java.sql.Connection;
7 import java.sql.DriverManager;
8 import java.sql.ResultSet;
9 import java.sql.Statement;
10 import java.util.UUID;
11
12 /**
13 * <p>ClassName: H2ConnTest1<p>
14 * <p>Description: Java通过JDBC方式连接H2数据库<p>
15 * @author xudp
16 * @version 1.0 V
17 * @createTime 2014-12-18 上午11:22:12
18 */
19 public class H2ConnTest2 {
20 //数据库连接URL,通过使用TCP/IP的服务器模式(远程连接),当前连接的是E:/H2目录下的gacl数据库
21 //private static final String JDBC_URL = "jdbc:h2:tcp://localhost/E:/H2/gacl";
22 //private static final String JDBC_URL = "jdbc:h2:tcp://127.0.0.1/E:/H2/gacl";
23 private static final String JDBC_URL = "jdbc:h2:tcp://192.168.1.144/data/gacl";
24 //连接数据库时使用的用户名
25 private static final String USER = "gacl";
26 //连接数据库时使用的密码
27 private static final String PASSWORD = "123";
28 //连接H2数据库时使用的驱动类,org.h2.Driver这个类是由H2数据库自己提供的,在H2数据库的jar包中可以找到
29 private static final String DRIVER_CLASS="org.h2.Driver";
30
31 public static void main(String[] args) throws Exception {
32 // 加载H2数据库驱动
33 Class.forName(DRIVER_CLASS);
34 // 根据连接URL,用户名,密码获取数据库连接
35 Connection conn = DriverManager.getConnection(JDBC_URL, USER, PASSWORD);
36 Statement stmt = conn.createStatement();
37 //如果存在USER_INFO表就先删除USER_INFO表
38 stmt.execute("DROP TABLE IF EXISTS USER_INFO");
39 //创建USER_INFO表
40 stmt.execute("CREATE TABLE USER_INFO(id VARCHAR(36) PRIMARY KEY,name VARCHAR(100),sex VARCHAR(4))");
41 //新增
42 stmt.executeUpdate("INSERT INTO USER_INFO VALUES('" + UUID.randomUUID()+ "','大日如来','男')");
43 stmt.executeUpdate("INSERT INTO USER_INFO VALUES('" + UUID.randomUUID()+ "','青龙','男')");
44 stmt.executeUpdate("INSERT INTO USER_INFO VALUES('" + UUID.randomUUID()+ "','白虎','男')");
45 stmt.executeUpdate("INSERT INTO USER_INFO VALUES('" + UUID.randomUUID()+ "','朱雀','女')");
46 stmt.executeUpdate("INSERT INTO USER_INFO VALUES('" + UUID.randomUUID()+ "','玄武','男')");
47 stmt.executeUpdate("INSERT INTO USER_INFO VALUES('" + UUID.randomUUID()+ "','苍狼','男')");
48 //删除
49 stmt.executeUpdate("DELETE FROM USER_INFO WHERE name='大日如来'");
50 //修改
51 stmt.executeUpdate("UPDATE USER_INFO SET name='孤傲苍狼' WHERE name='苍狼'");
52 //查询
53 ResultSet rs = stmt.executeQuery("SELECT * FROM USER_INFO");
54 //遍历结果集
55 while (rs.next()) {
56 System.out.println(rs.getString("id") + "," + rs.getString("name")+ "," + rs.getString("sex"));
57 }
58 //释放资源
59 stmt.close();
60 //关闭连接
61 conn.close();
62 }
63 }
2.3、H2数据库的内存模式
H2数据库被称为内存数据库,因为它支持在内存中创建数据库和表
范例如下:
1 package jdbc.conn.h2.test;
2
3 import java.sql.Connection;
4 import java.sql.DriverManager;
5 import java.sql.ResultSet;
6 import java.sql.Statement;
7 import java.util.UUID;
8
9 /**
10 * @ClassName: TestMemH2
11 * @Description:H2数据库的内存模式(数据只保存在内存中)
12 * @author: 孤傲苍狼
13 * @date: 2014-12-18 下午10:47:01
14 *
15 */
16 public class TestMemH2 {
17
18 //数据库连接URL,通过使用TCP/IP的服务器模式(远程连接),当前连接的是内存里面的gacl数据库
19 private static final String JDBC_URL = "jdbc:h2:tcp://localhost/mem:gacl";
20 //连接数据库时使用的用户名
21 private static final String USER = "gacl";
22 //连接数据库时使用的密码
23 private static final String PASSWORD = "123";
24 //连接H2数据库时使用的驱动类,org.h2.Driver这个类是由H2数据库自己提供的,在H2数据库的jar包中可以找到
25 private static final String DRIVER_CLASS="org.h2.Driver";
26
27 public static void main(String[] args) throws Exception {
28 // 加载H2数据库驱动
29 Class.forName(DRIVER_CLASS);
30 // 根据连接URL,用户名,密码获取数据库连接
31 Connection conn = DriverManager.getConnection(JDBC_URL, USER, PASSWORD);
32 Statement stmt = conn.createStatement();
33 //如果存在USER_INFO表就先删除USER_INFO表
34 stmt.execute("DROP TABLE IF EXISTS USER_INFO");
35 //创建USER_INFO表
36 stmt.execute("CREATE TABLE USER_INFO(id VARCHAR(36) PRIMARY KEY,name VARCHAR(100),sex VARCHAR(4))");
37 //新增
38 stmt.executeUpdate("INSERT INTO USER_INFO VALUES('" + UUID.randomUUID()+ "','大日如来','男')");
39 stmt.executeUpdate("INSERT INTO USER_INFO VALUES('" + UUID.randomUUID()+ "','青龙','男')");
40 stmt.executeUpdate("INSERT INTO USER_INFO VALUES('" + UUID.randomUUID()+ "','白虎','男')");
41 stmt.executeUpdate("INSERT INTO USER_INFO VALUES('" + UUID.randomUUID()+ "','朱雀','女')");
42 stmt.executeUpdate("INSERT INTO USER_INFO VALUES('" + UUID.randomUUID()+ "','玄武','男')");
43 stmt.executeUpdate("INSERT INTO USER_INFO VALUES('" + UUID.randomUUID()+ "','苍狼','男')");
44 //删除
45 stmt.executeUpdate("DELETE FROM USER_INFO WHERE name='大日如来'");
46 //修改
47 stmt.executeUpdate("UPDATE USER_INFO SET name='孤傲苍狼' WHERE name='苍狼'");
48 //查询
49 ResultSet rs = stmt.executeQuery("SELECT * FROM USER_INFO");
50 //遍历结果集
51 while (rs.next()) {
52 System.out.println(rs.getString("id") + "," + rs.getString("name")+ "," + rs.getString("sex"));
53 }
54 //释放资源
55 stmt.close();
56 //关闭连接
57 conn.close();
58 }
59 }
运行结果如下:
注意:如果使用H2数据库的内存模式,那么我们创建的数据库和表都只是保存在内存中,一旦服务器重启,那么内存中的数据库和表就不存在了。
以上就是关于在Web应用程序中使用H2数据库的全部内容。
一、搭建测试环境和项目
1.1、搭建JavaWeb测试项目
创建一个【H2DBTest】JavaWeb项目,找到H2数据库的jar文件,如下图所示:
H2数据库就一个jar文件,这个Jar文件里面包含了使用JDBC方式连接H2数据库时使用的驱动类,将"h2-1.4.183.jar"加入到【H2DBTest】项目中,如下图所示:
二、启动H2数据库
既然是要将H2数据库作为我们Web应用的一部分嵌入进来,那么我们就要在Web应用中启动H2数据库的服务,这样我们才能够连接到H2数据库,因此我们可以编写一个专门用于启动H2数据库服务的监听器(Listener),监听器示例代码如下:
1 package me.gacl.web.listener;
2
3 import java.sql.SQLException;
4 import javax.servlet.ServletContextEvent;
5 import javax.servlet.ServletContextListener;
6 import org.h2.tools.Server;
7
8 /**
9 * @ClassName: H2DBServerStartListener
10 * @Description: 用于启动H2数据库服务的监听器,在应用系统初始化时就启动H2数据库的服务
11 * @author: 孤傲苍狼
12 * @date: 2014-12-20 下午11:43:39
13 *
14 */
15 public class H2DBServerStartListener implements ServletContextListener {
16
17 //H2数据库服务器启动实例
18 private Server server;
19 /*
20 * Web应用初始化时启动H2数据库
21 */
22 public void contextInitialized(ServletContextEvent sce) {
23 try {
24 System.out.println("正在启动h2数据库...");
25 //使用org.h2.tools.Server这个类创建一个H2数据库的服务并启动服务,由于没有指定任何参数,那么H2数据库启动时默认占用的端口就是8082
26 server = Server.createTcpServer().start();
27 System.out.println("h2数据库启动成功...");
28 } catch (SQLException e) {
29 System.out.println("启动h2数据库出错:" + e.toString());
30 e.printStackTrace();
31 throw new RuntimeException(e);
32 }
33 }
34
35 /*
36 * Web应用销毁时停止H2数据库
37 */
38 public void contextDestroyed(ServletContextEvent sce) {
39 if (this.server != null) {
40 // 停止H2数据库
41 this.server.stop();
42 this.server = null;
43 }
44 }
45 }
监听器写好之后,我们在Web.xml文件中注册这个监听器,另外,因为我们要将H2数据库嵌入到我们的Web应用当中,为了能够方便访问H2数据库提供的Console,我们可以在Web.xml文件中配置用于访问H2数据库Console的Servlet。
Web.xml文件的配置如下:
1 <!-- 使用监听器启动和停止数据库 -->
2 <listener>
3 <listener-class>me.gacl.web.listener.H2DBServerStartListener</listener-class>
4 </listener>
5
6 <!-- 使用H2控制台的Servlet H2控制台是一个独立的应用程序,包括它自己的Web服务器,但它可以作为一个servlet作为-->
7 <servlet>
8 <servlet-name>H2Console</servlet-name>
9 <servlet-class>org.h2.server.web.WebServlet</servlet-class>
10 <init-param>
11 <param-name>webAllowOthers</param-name>
12 <param-value></param-value>
13 </init-param>
14 <init-param>
15 <param-name>trace</param-name>
16 <param-value></param-value>
17 </init-param>
18 <load-on-startup>1</load-on-startup>
19 </servlet>
20 <!-- 映射H2控制台的访问路径 -->
21 <servlet-mapping>
22 <servlet-name>H2Console</servlet-name>
23 <url-pattern>/console/*</url-pattern>
24 </servlet-mapping>
配置好Listener和访问Console的Servlet之后,我们就可以把H2数据库当作是我们Web应用中的一部分来使用了。
将Web应用部署到Tomcat服务器,当启动Tomcat服务器时,在控制台就可以看到H2数据库启动成功的消息,如下图所示:
为了进一步验证H2数据库是否真的是通过监听器正常启动了,我们可以访问一下H2数据库的Console,输入访问地址:“http://localhost:8080/H2DBTest/console/“进行访问,如下图所示:
能够看到H2数据库Console的登录页面,说明了H2数据库已经正常启动了。
三、向H2数据库注册自定义的数据库函数
H2作为一个数据库,和其他类型的数据库一样,会自带有一些数据库函数给我们使用,但是H2数据库提供的数据库函数有限,无法满足我们开发中的需求,幸运的是,H2数据库支持自定义数据库函数的,因此我们可以根据开发中的实际应用场景编写满足我们需求的数据库函数。
下面就来说一下如何实现H2数据库的自定义函数
在MySQL数据库中有一个UUID函数是用来生成UUID的,执行"SELECT UUID()“就可以看到UUID函数生成的UUID,如下图所示:
而默认情况下,H2数据库是没有提供有UUID这个函数给我们使用的,如下图所示:
那么我们现在就来实现一个UUID函数,然后注册到H2数据库当中,这样H2数据库就支持UUID函数了,具体做法分为两个步骤:
(1) 使用Java实现自定义函数的方法。
(2) 将Java的自定义函数注册到H2数据库中。
首先我们来实现这个UUID函数,在java中,生成一个UUID的方法是使用java.util.UUID这个类里面的一个randomUUID()方法生成的,封装成一个uuid方法,代码如下:
1 package h2db.function.ext;
2
3 import java.util.UUID;
4
5 /**
6 * @ClassName: H2DBFunctionExt
7 * @Description: 针对H2数据库函数的扩展
8 * @author: 孤傲苍狼
9 * @date: 2014-12-20 下午11:20:34
10 *
11 */
12 public class H2DBFunctionExt {
13
14 /**
15 * 用法:SELECT uuid();
16 * H2数据库注册uuid函数:CREATE ALIAS uuid FOR "h2db.function.ext.H2DBFunctionExt.uuid";
17 * @Method: uuid
18 * @Description: 实现MySQL数据库的uuid函数,用于生成UUID
19 * @Anthor:孤傲苍狼
20 *
21 * @return
22 */
23 public static String uuid(){
24 return UUID.randomUUID().toString();
25 }
26 }
这样,我们的uuid函数就算是编写好了,需要注意的是,类和方法必须是公共(Public)的,且方法需为静态(static)的,如方法中使用了Connection对象需将其关闭。
接下来我们要将其注册到H2数据库中,须执行"CREATE ALIAS"语句,SQL语法如下:
1 CREATE ALIAS [IF NOT EXISTS] newFunctionAliasName [DETERMINISTIC] FOR classAndMethodName
其中[]括起来的部分是可选的,本例须执行的语句为:
CREATE ALIAS UUID FOR “h2db. function .ext.H2DBFunctionExt.uuid” ,执行结果如下图所示:
这样H2数据库中就多了一个UUID函数可以使用了,我们再次执行"SELECT UUID()“语句就可以被H2数据库正常解析了,执行结果如下图所示:
以上就是针对H2数据库函数的一个扩展,我们向H2数据库新增加了一个UUID函数用于生成uuid。因此当H2数据库提供的函数不满足我们开发中的实际需求时,就可以使用这种方式来扩展H2数据库的函数了。接下来演示一下一次性向H2数据库扩展多个函数,我们编写一个H2DBFunctionExt类,在类中编写针对H2数据库的扩展函数,代码如下:
1 package h2db.function.ext;
2
3 import java.net.InetAddress;
4 import java.net.UnknownHostException;
5 import java.text.ParseException;
6 import java.text.SimpleDateFormat;
7 import java.util.Date;
8 import java.util.UUID;
9
10 /**
11 * @ClassName: H2DBFunctionExt
12 * @Description: 针对H2数据库函数的扩展
13 * @author: 孤傲苍狼
14 * @date: 2014-12-20 下午11:20:34
15 *
16 */
17 public class H2DBFunctionExt {
18
19 /**
20 * 用法:SELECT uuid();
21 * H2数据库注册uuid函数:CREATE ALIAS IF NOT EXISTS uuid FOR "h2db.function.ext.H2DBFunctionExt.uuid";
22 * @Method: uuid
23 * @Description: 实现MySQL数据库的uuid函数,用于生成UUID
24 * @Anthor:孤傲苍狼
25 *
26 * @return
27 */
28 public static String uuid(){
29 return UUID.randomUUID().toString();
30 }
31
32 /**
33 * H2数据库注册currentTime函数:CREATE ALIAS IF NOT EXISTS currentTime FOR "h2db.function.ext.H2DBFunctionExt.now";
34 * @Method: now
35 * @Description: 实现MySQL数据库的now()函数,用于生成当前系统时间
36 * @Anthor:孤傲苍狼
37 *
38 * @return
39 */
40 public static String now(){
41 return new Date().toLocaleString();
42 }
43
44 /**
45 * H2数据库注册IP函数:CREATE ALIAS IF NOT EXISTS IP FOR "h2db.function.ext.H2DBFunctionExt.getIp";
46 * @Method: getIp
47 * @Description:
48 * @Anthor:孤傲苍狼
49 *
50 * @return
51 */
52 public static String getIp(){
53 try {
54 InetAddress addr = InetAddress.getLocalHost();
55 //获得本机IP
56 return addr.getHostAddress();
57 } catch (UnknownHostException e) {
58 e.printStackTrace();
59 return "未知的IP地址";
60 }
61 }
62
63 /**
64 * H2数据库注册date_format函数:CREATE ALIAS IF NOT EXISTS date_format FOR "h2db.function.ext.H2DBFunctionExt.date_format";
65 * @Method: date_format
66 * @Description: 实现MySQL数据库的date_format()函数,用于格式化日期
67 * @Anthor:孤傲苍狼
68 * @param date
69 * @param pattern
70 * @return
71 */
72 public static String date_format(String date,String pattern){
73 if (date != null) {
74 SimpleDateFormat sdf = new SimpleDateFormat(pattern);
75 try {
76 Date temp = sdf.parse(date);
77 return sdf.format(temp);
78 } catch (ParseException e) {
79 e.printStackTrace();
80 }
81 }
82 return "";
83 }
84 }
为了实现批量注册H2数据库的扩展函数,我们可以编写一个Servlet,专门用于注册扩展函数,代码如下:
1 package me.gacl.sys.init;
2
3
4 import java.sql.Connection;
5 import java.sql.Statement;
6
7 import javax.servlet.ServletException;
8 import javax.servlet.http.HttpServlet;
9
10 import me.gacl.util.JdbcUtil;
11
12 /**
13 * @ClassName: RegisterH2ExtFuncServlet
14 * @Description:注册H2数据库的扩展函数
15 * @author: 孤傲苍狼
16 * @date: 2014-12-20 下午11:47:03
17 *
18 */
19 public class RegisterH2ExtFuncServlet extends HttpServlet {
20
21 /**
22 * @Field: serialVersionUID
23 */
24 private static final long serialVersionUID = 4379248469825545593L;
25
26 public void init() throws ServletException {
27 //1、注册uuid函数的SQL语句
28 String sql1 = "CREATE ALIAS IF NOT EXISTS uuid FOR \"h2db.function.ext.H2DBFunctionExt.uuid\"";
29 //2、注册currentTime函数的SQL语句
30 String sql2 = "CREATE ALIAS IF NOT EXISTS currentTime FOR \"h2db.function.ext.H2DBFunctionExt.now\"";
31 //3、注册IP函数的SQL语句
32 String sql3 = "CREATE ALIAS IF NOT EXISTS IP FOR \"h2db.function.ext.H2DBFunctionExt.getIp\"";
33 //4、注册date_format函数的SQL语句
34 String sql4 = "CREATE ALIAS IF NOT EXISTS date_format FOR \"h2db.function.ext.H2DBFunctionExt.date_format\"";
35 Connection connection = null;
36 Statement stmt = null;
37 try {
38 //获取数据库连接
39 connection = JdbcUtil.getConnection();
40 //获取Statement对象
41 stmt = connection.createStatement();
42 //添加要执行的SQL
43 stmt.addBatch(sql1);
44 stmt.addBatch(sql2);
45 stmt.addBatch(sql3);
46 stmt.addBatch(sql4);
47 //批量执行上述的4条SQL
48 stmt.executeBatch();
49 System.out.println("H2数据库扩展函数注册成功!");
50 stmt.clearBatch();
51 } catch (Exception e) {
52 System.out.println("H2数据库扩展函数注册失败!");
53 e.printStackTrace();
54 }finally{
55 try {
56 stmt.close();
57 connection.close();
58 } catch (Exception e2) {
59 e2.printStackTrace();
60 }
61 }
62 }
63 }
在Web.xml中注册RegisterH2ExtFuncServlet
1 <servlet>
2 <description>注册H2数据库的扩展函数</description>
3 <servlet-name>RegisterH2DBExtFunction</servlet-name>
4 <servlet-class>me.gacl.sys.init.RegisterH2ExtFuncServlet</servlet-class>
5 <!--
6 1、load-on-startup元素标记容器是否在启动的时候就加载这个servlet(实例化并调用其init()方法)。
7 2、它的值必须是一个整数,表示servlet应该被载入的顺序
8 3、当值为0或者大于0时,表示容器在应用启动时就加载并初始化这个servlet;
9 4、当值小于0或者没有指定时,则表示容器在该servlet被选择时才会去加载。
10 5、正数的值越小,该servlet的优先级越高,应用启动时就越先加载。
11 6、当值相同时,容器就会自己选择顺序来加载。
12 所以,<load-on-startup>x</load-on-startup>,中x的取值1,2,3,4,5代表的是优先级,而非启动延迟时间。
13 -->
14 <load-on-startup>1</load-on-startup>
15 </servlet>
RegisterH2ExtFuncServlet要批量执行SQL语句,因此需要连接上H2数据库才能够执行,工具类JdbcUtil提供了获取数据库连接的方法,JdbcUtil的代码如下:
1 /**
2 *
3 */
4 package me.gacl.util;
5
6 import java.io.InputStream;
7 import java.sql.Connection;
8 import java.util.Properties;
9 import org.h2.jdbcx.JdbcConnectionPool;
10
11 public class JdbcUtil {
12
13 /**
14 * H2数据库自带的连接池
15 */
16 private static JdbcConnectionPool cp = null;
17
18 static{
19 try {
20 //加载src目录下的h2config.properties
21 InputStream in = JdbcUtil.class.getClassLoader().getResourceAsStream("h2config.properties");
22 Properties prop = new Properties();
23 prop.load(in);
24 //创建数据库连接池
25 cp = JdbcConnectionPool.create(prop.getProperty("JDBC_URL"), prop.getProperty("USER"), prop.getProperty("PASSWORD"));
26 } catch (Exception e) {
27 System.out.println("连接池初始化异常");
28 e.printStackTrace();
29 }
30 }
31
32 /**
33 * @Method: getConnection
34 * @Description:获取数据库连接
35 * @Anthor:孤傲苍狼
36 * @return
37 * @throws Exception
38 */
39 public static Connection getConnection() throws Exception{
40 return cp.getConnection();
41 }
42
43 public static JdbcConnectionPool getCp() {
44 return cp;
45 }
46 }
h2config.properties的配置信息如下:
JDBC_URL=jdbc:h2:tcp://localhost/~/h2db
USER=gacl
PASSWORD=123
当web应用启动时,就会执行RegisterH2ExtFuncServlet这个Servlet中的init方法,init方法内部的处理就是通过JdbcUtil工具类获取一个H2的数据库连接,然后创建Statement对象,再由Statement对象批量执行SQL向H2数据库注册扩展函数。
RegisterH2ExtFuncServlet执行的过程中如果没有出现任何错误,那就说明所有的针对H2数据库的扩展函数都注册成功了,我们可以到H2的Console去验证一下上述的4个扩展函数,如下图所示:
关于在Web应用中嵌入使用H2数据库,以及针对H2数据库函数的扩展的内容就讲解这么多了。