Java在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),监听器示例代码如下:

 

 代码如下 复制代码

package me.gacl.web.listener;

import java.sql.SQLException;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import org.h2.tools.Server;

/**
* @ClassName: H2DBServerStartListener
* @Description: 用于启动H2数据库服务的监听器,在应用系统初始化时就启动H2数据库的服务
* @author: 孤傲苍狼
* @date: 2014-12-20 下午11:43:39
*
*/
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数据库Console的Servlet。

Web.xml文件的配置如下:

 

 代码如下 复制代码
<!-- 使用监听器启动和停止数据库 -->
      <listener>
        <listener-class>me.gacl.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和访问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方法,代码如下:

 

 代码如下 复制代码

package h2db.function.ext;

import java.util.UUID;

/**
* @ClassName: H2DBFunctionExt
* @Description: 针对H2数据库函数的扩展
* @author: 孤傲苍狼
* @date: 2014-12-20 下午11:20:34
*
*/
public class H2DBFunctionExt {

    /**
    * 用法:SELECT uuid();
    * H2数据库注册uuid函数:CREATE ALIAS uuid FOR "h2db.function.ext.H2DBFunctionExt.uuid";
    * @Method: uuid
    * @Description: 实现MySQL数据库的uuid函数,用于生成UUID
    * @Anthor:孤傲苍狼
    *
    * @return
    */
    public static String uuid(){
        return UUID.randomUUID().toString();
    }
}

 

这样,我们的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数据库的扩展函数,代码如下:

 

 代码如下 复制代码

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;

/**
* @ClassName: H2DBFunctionExt
* @Description: 针对H2数据库函数的扩展
* @author: 孤傲苍狼
* @date: 2014-12-20 下午11:20:34
*
*/
public class H2DBFunctionExt {

    /**
    * 用法:SELECT uuid();
    * H2数据库注册uuid函数:CREATE ALIAS IF NOT EXISTS uuid FOR "h2db.function.ext.H2DBFunctionExt.uuid";
    * @Method: uuid
    * @Description: 实现MySQL数据库的uuid函数,用于生成UUID
    * @Anthor:孤傲苍狼
    *
    * @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()函数,用于生成当前系统时间
    * @Anthor:孤傲苍狼
    *
    * @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:
    * @Anthor:孤傲苍狼
    *
    * @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()函数,用于格式化日期
    * @Anthor:孤傲苍狼
    * @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 me.gacl.sys.init;

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

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

import me.gacl.util.JdbcUtil;

/**
* @ClassName: RegisterH2ExtFuncServlet
* @Description:注册H2数据库的扩展函数
* @author: 孤傲苍狼
* @date: 2014-12-20 下午11:47:03
*
*/
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>me.gacl.sys.init.RegisterH2ExtFuncServlet</servlet-class>
    <!--
    1、load-on-startup元素标记容器是否在启动的时候就加载这个servlet(实例化并调用其init()方法)。
    2、它的值必须是一个整数,表示servlet应该被载入的顺序
    3、当值为0或者大于0时,表示容器在应用启动时就加载并初始化这个servlet;
    4、当值小于0或者没有指定时,则表示容器在该servlet被选择时才会去加载。
    5、正数的值越小,该servlet的优先级越高,应用启动时就越先加载。
    6、当值相同时,容器就会自己选择顺序来加载。
    所以,<load-on-startup>x</load-on-startup>,中x的取值1,2,3,4,5代表的是优先级,而非启动延迟时间。
     -->
     <load-on-startup>1</load-on-startup>
</servlet>

 

RegisterH2ExtFuncServlet要批量执行SQL语句,因此需要连接上H2数据库才能够执行,工具类JdbcUtil提供了获取数据库连接的方法,JdbcUtil的代码如下:

 

 代码如下 复制代码

/**
 *
 */
package me.gacl.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:获取数据库连接
    * @Anthor:孤傲苍狼
    * @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://localhost/~/h2db

USER=gacl

PASSWORD=123

当web应用启动时,就会执行RegisterH2ExtFuncServlet这个Servlet中的init方法,init方法内部的处理就是通过JdbcUtil工具类获取一个H2的数据库连接,然后创建Statement对象,再由Statement对象批量执行SQL向H2数据库注册扩展函数。

RegisterH2ExtFuncServlet执行的过程中如果没有出现任何错误,那就说明所有的针对H2数据库的扩展函数都注册成功了,我们可以到H2的Console去验证一下上述的4个扩展函数,如下图所示:

时间: 2024-09-24 01:12:20

Java在Web应用中嵌入H2数据库教程的相关文章

表单-关于WEB 开发中jsp访问数据库的问题

问题描述 关于WEB 开发中jsp访问数据库的问题 就如题目所说,我现在在做一个网页,现在写了几个bean ,能够实现读取网页表单中的数据 ,并且把他们写到数据库,下面要做的是,从数据库中读取符合条件的数据,并显示在网页中 符合条件的数据也是由网页输入的.问一下有那个大神会做吗,急!!! 解决方案 会啊,这种问题,只要是程序员都会做吧.你可以放心大胆雇佣一个程序员帮你了. 解决方案二: 你说的是输入输出是在同一个页面是吧 就是说一个页面进去之后表单中就有数据,并且他们可以修改 方法很多,举一个:

java 在web project中的jsp中怎么用dropzone.js实现拖拽上传

问题描述 java 在web project中的jsp中怎么用dropzone.js实现拖拽上传 我现在想做一个拖拽上传,看别人说用dropzone.js!能做,想请大神解答!图片说明 解决方案 好了,自己解决了 ,谢谢各位 解决方案二: http://danielm.herokuapp.com/demos/dnd/image-preview.php http://download.csdn.net/download/u014166482/7753273

java 在web页面中把输入框的中文用语音读出来有什么办法?

问题描述 请问下大家,java在web页面中把输入框的中文用语音读出来有什么办法?我在网上找到一个freetts引擎可以实现java语音,但是中文读取的话太不标准了,根本听不懂.请问大家有没有其他免费的引擎,或者是可以调用window自带的方法,因为window有自带的语音,如果能用dll或者其他的方法调用,那就方便很多了,或者是其他一些思路也行,先谢谢大家了. 解决方案 解决方案二:该回复于2010-11-10 09:57:24被版主删除解决方案三:该回复于2010-11-10 15:21:3

Java Web项目中连接Access数据库的配置方法_JSP编程

老师决定期末考试采用access数据库实现增删改查,我认为现在的我已经没有问题了,但是以前都是在JSP页面中连接access数据库,无论是以下的那种方式都进行了连接的练习,但是现在我想让我的项目中的访问access数据库的java代码,封装到DAO中,在DAO中连接数据库,没有和Servlet API有任何的关系.对于大多数人都会优先选择使用ODBC数据源的方式或者是使用绝对路径的方式连接access数据库,但是我个人认为,这样做不太好,如果采用这样的方式,项目做好后,放到他人的服务器上是无法运

java的web.xml中context-param与init-param的区别介绍

web.xml中<context-param>与<init-param>的区别在于<context-param>设置的是一个在应用中全局(ServletContext范围内)可见的参数,而<init-param>设置的是一个在应用中局部(ServletRequest范围内)可见的参数. <?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi=

Java的Hibernate框架中用于操作数据库的HQL语句讲解_java

 上次我们一起学习了用Criteria进行相关的操作,但由于Criteria并不是Hibernate官方推荐的查询方式,我们也并不多用.现在我们来看一下官方推荐的HQL,一起学习一下它的强大.  说是HQL,也就是Hibernate查询语句,和SQL有什么区别呢?一个字母的区别,哈哈.  当然不是这样,HQL和SQL的区别在于思想的不同,HQL是用面向对象的方向进行查询,而SQL则是对数据库二维表进行查询,这里包含的是思想的不同.HQL实际上也是SQL,它由Hibernate帮我们在内部进行转换

Java的web开发中SSH框架的协作处理应用笔记_java

 相信SSH没人不知道了吧,struts2+spring+hibernate,企业开发的"基础"架构,为什么基础标上引号,因为这个基础只是很多人自以为的而已,最基础的是servlet,很多培训机构很多基础都不教,直接上来就三大框架了,SSH不然就SSI,搞得很多人以为JAVAWEB开发就一定要框架,没框架就跟没了手一个样.三大框架没有什么坏处,实用,很多公司都在用,直接上手开发.但毕业以为真的好久没用三大框架了,spring倒是有用,特别是springMVC,感觉用起来比struts2

在WEB标准中嵌入Flash 的最佳方法

Flash 嵌入的问题论坛中有人问了好多次,到底应该怎么用,为什么通不过验证,要通过验证怎么办等等等.讨论中也出现了不少的误解,所以我单开一个帖总结一下我所知道的东西,不想看我罗嗦的直接跳到最后看结论就可以了. 一.传统的方法.<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000"    codebase="http://fpdownload.macromedia.com/pub/shockwave/ca

在Java的Spring框架中配置Quartz的教程_java

Spring中配置Quartz的过程: 1.导入JAR包 quartz需要的JAR包,已经包含在spring中,位置在spring解压后目录的 \lib\quartz 下的quartz-all-1.6.1.jar, 将其拷贝到工程 的 WEB-INF/lib 下就行了. 2.配置web.xml,让spring启动时加载quartz的配置文件 <?xml version="1.0" encoding="UTF-8"?> <web-app versio