H2数据库入门总结(三)

本文介绍如何将H2数据库嵌入Web应用,并通过监听器自动启动数据库服务。此外,还介绍了如何自定义数据库函数并通过SQL语句注册这些函数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

H2作为一个嵌入型的数据库,它最大的好处就是可以嵌入到我们的Web应用中,和我们的Web应用绑定在一起,成为我们Web应用的一部分。下面来演示一下如何将H2数据库嵌入到我们的Web应用中。

一、搭建Web测试项目

创建一个H2DBTest 项目,找到H2数据库jar文件


H2数据库就是一个jar文件,这个jar文件里包含了使用JDBC方式连接H2数据库时使用的驱动类,将该jar放到项目中


二、启动H2数据库

既然是要将H2数据库作为我们Web应用的一部分嵌入进来,那么我们就要在Web应用中启动H2数据库的服务,这样我们才能够连接到H2数据库,因此我们可以编写一个专门用于启动H2数据库服务的监听器(Listener),监听器示例代码如下:

package com.jiaox.web.listener;

import java.sql.SQLException;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

import org.h2.tools.Server;

public class H2DBServerStartListener implements ServletContextListener {
	//H2数据库服务器启动实例
	    private Server server;
	     /* 
	      * Web应用初始化时启动H2数据库
	      */
	     public void contextInitialized(ServletContextEvent sce) {
	         try {  
	             System.out.println("正在启动h2数据库...");
	             //使用org.h2.tools.Server这个类创建一个H2数据库的服务并启动服务,由于没有指定任何参数,那么H2数据库启动时默认占用的端口就是8082
	             server = Server.createTcpServer().start(); 
	             System.out.println("h2数据库启动成功...");
	         } catch (SQLException e) {  
	             System.out.println("启动h2数据库出错:" + e.toString());  
	             e.printStackTrace();  
	             throw new RuntimeException(e);  
	         }  
	     }
	 
	     /* 
	      * Web应用销毁时停止H2数据库
	      */
	     public void contextDestroyed(ServletContextEvent sce) {
	         if (this.server != null) {
	             // 停止H2数据库
	             this.server.stop();
	             this.server = null;
	         }
	     }
}

监听器写好之后,我们在Web.xml文件中注册这个监听器,另外,因为我们要将H2数据库嵌入到我们的Web应用当中,为了能够方便访问H2数据库提供的Console,我们可以在Web.xml文件中配置用于访问H2数据库ConsoleServlet

Web.xml文件的配置如下:

<!-- 使用监听器启动和停止数据库 -->
	<listener>
		<listener-class>com.jiaox.web.listener.H2DBServerStartListener</listener-class>
	</listener>

	<!-- 使用H2控制台的Servlet H2控制台是一个独立的应用程序,包括它自己的Web服务器,但它可以作为一个servlet作为 -->
	<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>
        <!-- 映射H2控制台的访问路径 -->
	<servlet-mapping>
		<servlet-name>H2Console</servlet-name>
		<url-pattern>/console/*</url-pattern>
	</servlet-mapping>

配置好Listener和访问ConsoleServlet之后,我们就可以把H2数据库当作是我们Web应用中的一部分来使用了。Web应用部署到Tomcat服务器,当启动Tomcat服务器时,在控制台就可以看到H2数据库启动成功的消息,如下图所示:


为了进一步验证H2数据库是否真的是通过监听器正常启动了,(注意,仅仅是启动了服务,项目中的数据库文件还没有创建)我们可以访问一下H2数据库的Console,输入访问地址:"http://localhost:9999/H2DBTest/console/"进行访问,如下图所示:


能够看到H2数据库Console的登录页面,说明了H2数据库已经正常启动了。登录如图的JDBC URL,就在项目中创建了一个数据库文件。


三、向数据库注册自定义的数据库函数

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方法,代码如下:
package h2db.function.ext;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.UUID;

public class H2DBFunctionExt {
	/**
	 * 用法:SELECT uuid(); H2数据库注册uuid函数:CREATE ALIAS uuid FOR
	 * "h2db.function.ext.H2DBFunctionExt.uuid";
	 * 
	 * @Method: uuid
	 * @Description: 实现MySQL数据库的uuid函数,用于生成UUID
	 * 
	 * @return
	 */
	public static String uuid() {
		return UUID.randomUUID().toString();
	}
}
这样,我们的uuid函数就算是编写好了,需要注意的是,类和方法必须是公共(Public),且方法需为静态(static)的,如方法中使用了Connection对象需将其关闭。

接下来我们要将其注册到H2数据库中,须执行"CREATE ALIAS"语句,SQL语法如下:

CREATE ALIAS [IF NOT EXISTS] newFunctionAliasName [DETERMINISTIC] FOR classAndMethodName

其中[]括起来的部分是可选的,本例须执行的语句为:

CREATE ALIASUUID FOR "h2db.function.ext.H2DBFunctionExt.uuid" 

这样H2数据库中就多了一个UUID函数可以使用了,我们再次执行"SELECTUUID()"语句就可以被H2数据库正常解析了。

以上就是针对H2数据库函数的一个扩展,我们向H2数据库新增加了一个UUID函数用于生成uuid。因此当H2数据库提供的函数不满足我们开发中的实际需求时,就可以使用这种方式来扩展H2数据库的函数了。接下来演示一下一次性向H2数据库扩展多个函数,我们编写一个H2DBFunctionExt类,在类中编写针对H2数据库的扩展函数,代码如下:

package h2db.function.ext;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.UUID;
public class H2DBFunctionExt {
	/**
	 * 用法:SELECT uuid(); H2数据库注册uuid函数:CREATE ALIAS uuid FOR
	 * "h2db.function.ext.H2DBFunctionExt.uuid";
	 * 
	 * @Method: uuid
	 * @Description: 实现MySQL数据库的uuid函数,用于生成UUID
	 * 
	 * @return
	 */
	public static String uuid() {
		return UUID.randomUUID().toString();
	}

	/**
	 * H2数据库注册currentTime函数:CREATE ALIAS IF NOT EXISTS currentTime FOR
	 * "h2db.function.ext.H2DBFunctionExt.now";
	 * 
	 * @Method: now
	 * @Description: 实现MySQL数据库的now()函数,用于生成当前系统时间
	 * 
	 * @return
	 */
	public static String now() {
		return new Date().toLocaleString();
	}

	/**
	 * H2数据库注册IP函数:CREATE ALIAS IF NOT EXISTS IP FOR
	 * "h2db.function.ext.H2DBFunctionExt.getIp";
	 * 
	 * @Method: getIp
	 * @Description:
	 * 
	 * @return
	 */
	public static String getIp() {
		try {
			InetAddress addr = InetAddress.getLocalHost();
			// 获得本机IP
			return addr.getHostAddress();
		} catch (UnknownHostException e) {
			e.printStackTrace();
			return "未知的IP地址";
		}
	}

	/**
	 * H2数据库注册date_format函数:CREATE ALIAS IF NOT EXISTS date_format FOR
	 * "h2db.function.ext.H2DBFunctionExt.date_format";
	 * 
	 * @Method: date_format
	 * @Description: 实现MySQL数据库的date_format()函数,用于格式化日期
	 * @param date
	 * @param pattern
	 * @return
	 */
	public static String date_format(String date, String pattern) {
		if (date != null) {
			SimpleDateFormat sdf = new SimpleDateFormat(pattern);
			try {
				Date temp = sdf.parse(date);
				return sdf.format(temp);
			} catch (ParseException e) {
				e.printStackTrace();
			}
		}
		return "";
	}

}
为了实现批量注册H2数据库的扩展函数,我们可以编写一个Servlet,专门用于注册扩展函数,代码如下:
package com.jiaox.sys.init;

import java.sql.Connection;
import java.sql.Statement;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;

import com.jiaox.util.JdbcUtil;

public class RegisterH2ExtFuncServlet extends HttpServlet {

	/**
	 * @Field: serialVersionUID
	 */
	private static final long serialVersionUID = 4379248469825545593L;

	public void init() throws ServletException {
		// 1、注册uuid函数的SQL语句
//		String sql1 = "CREATE ALIAS IF NOT EXISTS uuid FOR \"h2db.function.ext.H2DBFunctionExt.uuid\"";
		// 2、注册currentTime函数的SQL语句
		String sql2 = "CREATE ALIAS IF NOT EXISTS currentTime FOR \"h2db.function.ext.H2DBFunctionExt.now\"";
		// 3、注册IP函数的SQL语句
		String sql3 = "CREATE ALIAS IF NOT EXISTS IP FOR \"h2db.function.ext.H2DBFunctionExt.getIp\"";
		// 4、注册date_format函数的SQL语句
		String sql4 = "CREATE ALIAS IF NOT EXISTS date_format FOR \"h2db.function.ext.H2DBFunctionExt.date_format\"";
		Connection connection = null;
		Statement stmt = null;
		try {
			// 获取数据库连接
			connection = JdbcUtil.getConnection();
			// 获取Statement对象
			stmt = connection.createStatement();
			// 添加要执行的SQL
//			stmt.addBatch(sql1);
			stmt.addBatch(sql2);
			stmt.addBatch(sql3);
			stmt.addBatch(sql4);
			// 批量执行上述的4条SQL
			stmt.executeBatch();
			System.out.println("H2数据库扩展函数注册成功!");
			stmt.clearBatch();
		} catch (Exception e) {
			System.out.println("H2数据库扩展函数注册失败!");
			e.printStackTrace();
		} finally {
			try {
				stmt.close();
				connection.close();
			} catch (Exception e2) {
				e2.printStackTrace();
			}
		}
	}
}
Web.xml中注册RegisterH2ExtFuncServlet
        <servlet>
		<description>注册H2数据库的扩展函数</description>
		<servlet-name>RegisterH2DBExtFunction</servlet-name>
		<servlet-class>com.jiaox.sys.init.RegisterH2ExtFuncServlet</servlet-class>		
		<load-on-startup>1</load-on-startup>
	</servlet>
RegisterH2ExtFuncServlet要批量执行SQL语句,因此需要连接上H2数据库才能够执行,工具类JdbcUtil提供了获取数据库连接的方法,JdbcUtil的代码如下:
package com.jiaox.util;

import java.io.InputStream;
import java.sql.Connection;
import java.util.Properties;

import org.h2.jdbcx.JdbcConnectionPool;

public class JdbcUtil {
     /**
      * H2数据库自带的连接池
      */
     private static JdbcConnectionPool cp = null;
     
     static{
         try {
             //加载src目录下的h2config.properties
             InputStream in = JdbcUtil.class.getClassLoader().getResourceAsStream("h2config.properties");
             Properties prop = new Properties();
             prop.load(in);
             //创建数据库连接池
             cp = JdbcConnectionPool.create(prop.getProperty("JDBC_URL"), prop.getProperty("USER"), prop.getProperty("PASSWORD"));
         } catch (Exception e) {
             System.out.println("连接池初始化异常");
             e.printStackTrace();
         }
     }
     
     /**
     * @Method: getConnection
     * @Description:获取数据库连接
     * @return
     * @throws Exception
     */ 
     public static Connection getConnection() throws Exception{
         return cp.getConnection();
     }
 
     public static JdbcConnectionPool getCp() {
         return cp;
     }

}

h2config.properties的配置信息如下:

JDBC_URL=jdbc:h2:tcp://127.0.0.1:9092/../webapps/H2DBTest/WEB-INF/h2/jiaox
USER=jiaox
PASSWORD=123

web应用启动时,就会执行RegisterH2ExtFuncServlet这个Servlet中的init方法,init方法内部的处理就是通过JdbcUtil工具类获取一个H2的数据库连接,然后创建Statement对象,再由Statement对象批量执行SQLH2数据库注册扩展函数。RegisterH2ExtFuncServlet执行的过程中如果没有出现任何错误,那就说明所有的针对H2数据库的扩展函数都注册成功了,我们可以到H2Console去验证一下上述的4个扩展函数,如下图所示:



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值