Java在Web应用程序中如何使用嵌入式数据库H2

一、搭建测试环境和项目

1.1、搭建JavaWeb测试项目

创建一个【H2DBTest】JavaWeb项目,找到H2数据库的jar文件,如下图所示:

H2数据库就一个jar文件,这个Jar文件里面包含了使用JDBC方式连接H2数据库时使用的驱动类,将"h2-1.4.183.jar"加入到【H2DBTest】项目中,如下图所示:

1.2、开启H2数据库

进入到h2bin目录,如下图所示:

确保H2数据库使用的8082端口没有被其他应用程序占用,正常启动之后输入"http://localhost:8082"进行简单的测试,如下图所示:

到此,使用Java操作H2数据库的测试环境就算是搭建完成了。

二、在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)

编写测试代码,如下:

 

 代码如下 复制代码

/**
 *
 */
package jdbc.conn.h2.test;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.UUID;

/**
 * <p>ClassName: H2ConnTest1<p>
 * <p>Description: Java通过JDBC方式连接H2数据库<p>
 * @author xudp
 * @version 1.0 V
 * @createTime 2014-12-18 上午11:22:12
 */
public class H2ConnTest1 {
    //数据库连接URL,当前连接的是E:/H2目录下的gacl数据库
    private static final String JDBC_URL = "jdbc:h2:E:/H2/gacl";
    //连接数据库时使用的用户名
    private static final String USER = "gacl";
    //连接数据库时使用的密码
    private static final String PASSWORD = "123";
    //连接H2数据库时使用的驱动类,org.h2.Driver这个类是由H2数据库自己提供的,在H2数据库的jar包中可以找到
    private static final String DRIVER_CLASS="org.h2.Driver";
   
    public static void main(String[] args) throws Exception {
        // 加载H2数据库驱动
        Class.forName(DRIVER_CLASS);
        // 根据连接URL,用户名,密码获取数据库连接
        Connection conn = DriverManager.getConnection(JDBC_URL, USER, PASSWORD);
        Statement stmt = conn.createStatement();
        //如果存在USER_INFO表就先删除USER_INFO表
        stmt.execute("DROP TABLE IF EXISTS USER_INFO");
        //创建USER_INFO表
        stmt.execute("CREATE TABLE USER_INFO(id VARCHAR(36) PRIMARY KEY,name VARCHAR(100),sex VARCHAR(4))");
        //新增
        stmt.executeUpdate("INSERT INTO USER_INFO VALUES('" + UUID.randomUUID()+ "','大日如来','男')");
        stmt.executeUpdate("INSERT INTO USER_INFO VALUES('" + UUID.randomUUID()+ "','青龙','男')");
        stmt.executeUpdate("INSERT INTO USER_INFO VALUES('" + UUID.randomUUID()+ "','白虎','男')");
        stmt.executeUpdate("INSERT INTO USER_INFO VALUES('" + UUID.randomUUID()+ "','朱雀','女')");
        stmt.executeUpdate("INSERT INTO USER_INFO VALUES('" + UUID.randomUUID()+ "','玄武','男')");
        stmt.executeUpdate("INSERT INTO USER_INFO VALUES('" + UUID.randomUUID()+ "','苍狼','男')");
        //删除
        stmt.executeUpdate("DELETE FROM USER_INFO WHERE name='大日如来'");
        //修改
        stmt.executeUpdate("UPDATE USER_INFO SET name='孤傲苍狼' WHERE name='苍狼'");
        //查询
        ResultSet rs = stmt.executeQuery("SELECT * FROM USER_INFO");
        //遍历结果集
        while (rs.next()) {
            System.out.println(rs.getString("id") + "," + rs.getString("name")+ "," + rs.getString("sex"));
        }
        //释放资源
        stmt.close();
        //关闭连接
        conn.close();
    }
}

 

执行结果如下:

登录到H2控制台当中也可以看到创建好的USER_INFO表和表里面的数据,如下图所示:

这里需要说明一下使用这种"jdbc:h2:E:/H2/gacl"这种方式连接H2数据库容易遇到的问题,如果已经在H2的WebConsole控制台中登录gacl数据库,如下图所示:

此时gacl数据库就会被锁定,此时通过java代码连接gacl数据库时就会出现如下的错误,如所示:

 

 代码如下 复制代码
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]
    at org.h2.message.DbException.getJdbcSQLException(DbException.java:345)
    at org.h2.message.DbException.get(DbException.java:168)
    at org.h2.mvstore.db.MVTableEngine.init(MVTableEngine.java:108)
    at org.h2.engine.Database.getPageStore(Database.java:2376)
    at org.h2.engine.Database.open(Database.java:666)
    at org.h2.engine.Database.openDatabase(Database.java:266)
    at org.h2.engine.Database.<init>(Database.java:260)
    at org.h2.engine.Engine.openSession(Engine.java:60)
    at org.h2.engine.Engine.openSession(Engine.java:167)
    at org.h2.engine.Engine.createSessionAndValidate(Engine.java:145)
    at org.h2.engine.Engine.createSession(Engine.java:128)
    at org.h2.engine.Engine.createSession(Engine.java:26)
    at org.h2.engine.SessionRemote.connectEmbeddedOrServer(SessionRemote.java:347)
    at org.h2.jdbc.JdbcConnection.<init>(JdbcConnection.java:108)
    at org.h2.jdbc.JdbcConnection.<init>(JdbcConnection.java:92)
    at org.h2.Driver.connect(Driver.java:72)
    at java.sql.DriverManager.getConnection(DriverManager.java:571)
    at java.sql.DriverManager.getConnection(DriverManager.java:215)
    at jdbc.conn.h2.test.H2ConnTest1.main(H2ConnTest1.java:33)
Caused by: java.lang.IllegalStateException: The file is locked: nio:E:/H2/gacl.mv.db [1.4.183/7]
    at org.h2.mvstore.DataUtils.newIllegalStateException(DataUtils.java:768)
    at org.h2.mvstore.FileStore.open(FileStore.java:170)
    at org.h2.mvstore.MVStore.<init>(MVStore.java:346)
    at org.h2.mvstore.MVStore$Builder.open(MVStore.java:2754)
    at org.h2.mvstore.db.MVTableEngine$Store.<init>(MVTableEngine.java:162)
    at org.h2.mvstore.db.MVTableEngine.init(MVTableEngine.java:98)
    ... 16 more

 

引起这个错误的原因是因为gacl数据库对应的文件已经被锁定了,所以java代码这边无法再访问,为了能够让Java代码能够正常访问,必须把WebConsole控制台那边的连接先断开,

断开数据库连接之后,Java代码这边就可以连接上去了。

2.2、使用TCP/IP的服务器模式(远程连接)方式连接H2数据库(推荐)

这种连接方式就和其他数据库类似了,是基于Service的形式进行连接的,因此允许多个客户端同时连接到H2数据库

连接语法:jdbc:h2:tcp://[:
]/[
]

范例:jdbc:h2:tcp://localhost/~/test

测试代码如下:

 

 代码如下 复制代码

/**
 *
 */
package jdbc.conn.h2.test;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.UUID;

/**
 * <p>ClassName: H2ConnTest1<p>
 * <p>Description: Java通过JDBC方式连接H2数据库<p>
 * @author xudp
 * @version 1.0 V
 * @createTime 2014-12-18 上午11:22:12
 */
public class H2ConnTest2 {
    //数据库连接URL,通过使用TCP/IP的服务器模式(远程连接),当前连接的是E:/H2目录下的gacl数据库
    //private static final String JDBC_URL = "jdbc:h2:tcp://localhost/E:/H2/gacl";
    //private static final String JDBC_URL = "jdbc:h2:tcp://127.0.0.1/E:/H2/gacl";
    private static final String JDBC_URL = "jdbc:h2:tcp://192.168.1.144/data/gacl";
    //连接数据库时使用的用户名
    private static final String USER = "gacl";
    //连接数据库时使用的密码
    private static final String PASSWORD = "123";
    //连接H2数据库时使用的驱动类,org.h2.Driver这个类是由H2数据库自己提供的,在H2数据库的jar包中可以找到
    private static final String DRIVER_CLASS="org.h2.Driver";
   
    public static void main(String[] args) throws Exception {
        // 加载H2数据库驱动
        Class.forName(DRIVER_CLASS);
        // 根据连接URL,用户名,密码获取数据库连接
        Connection conn = DriverManager.getConnection(JDBC_URL, USER, PASSWORD);
        Statement stmt = conn.createStatement();
        //如果存在USER_INFO表就先删除USER_INFO表
        stmt.execute("DROP TABLE IF EXISTS USER_INFO");
        //创建USER_INFO表
        stmt.execute("CREATE TABLE USER_INFO(id VARCHAR(36) PRIMARY KEY,name VARCHAR(100),sex VARCHAR(4))");
        //新增
        stmt.executeUpdate("INSERT INTO USER_INFO VALUES('" + UUID.randomUUID()+ "','大日如来','男')");
        stmt.executeUpdate("INSERT INTO USER_INFO VALUES('" + UUID.randomUUID()+ "','青龙','男')");
        stmt.executeUpdate("INSERT INTO USER_INFO VALUES('" + UUID.randomUUID()+ "','白虎','男')");
        stmt.executeUpdate("INSERT INTO USER_INFO VALUES('" + UUID.randomUUID()+ "','朱雀','女')");
        stmt.executeUpdate("INSERT INTO USER_INFO VALUES('" + UUID.randomUUID()+ "','玄武','男')");
        stmt.executeUpdate("INSERT INTO USER_INFO VALUES('" + UUID.randomUUID()+ "','苍狼','男')");
        //删除
        stmt.executeUpdate("DELETE FROM USER_INFO WHERE name='大日如来'");
        //修改
        stmt.executeUpdate("UPDATE USER_INFO SET name='孤傲苍狼' WHERE name='苍狼'");
        //查询
        ResultSet rs = stmt.executeQuery("SELECT * FROM USER_INFO");
        //遍历结果集
        while (rs.next()) {
            System.out.println(rs.getString("id") + "," + rs.getString("name")+ "," + rs.getString("sex"));
        }
        //释放资源
        stmt.close();
        //关闭连接
        conn.close();
    }
}

 

2.3、H2数据库的内存模式

H2数据库被称为内存数据库,因为它支持在内存中创建数据库和表

范例如下:

 

 代码如下 复制代码

package jdbc.conn.h2.test;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.UUID;

/**
* @ClassName: TestMemH2
* @Description:H2数据库的内存模式(数据只保存在内存中)
* @author: 孤傲苍狼
* @date: 2014-12-18 下午10:47:01
*
*/
public class TestMemH2 {

        //数据库连接URL,通过使用TCP/IP的服务器模式(远程连接),当前连接的是内存里面的gacl数据库
        private static final String JDBC_URL = "jdbc:h2:tcp://localhost/mem:gacl";
        //连接数据库时使用的用户名
        private static final String USER = "gacl";
        //连接数据库时使用的密码
        private static final String PASSWORD = "123";
        //连接H2数据库时使用的驱动类,org.h2.Driver这个类是由H2数据库自己提供的,在H2数据库的jar包中可以找到
        private static final String DRIVER_CLASS="org.h2.Driver";
       
        public static void main(String[] args) throws Exception {
            // 加载H2数据库驱动
            Class.forName(DRIVER_CLASS);
            // 根据连接URL,用户名,密码获取数据库连接
            Connection conn = DriverManager.getConnection(JDBC_URL, USER, PASSWORD);
            Statement stmt = conn.createStatement();
            //如果存在USER_INFO表就先删除USER_INFO表
            stmt.execute("DROP TABLE IF EXISTS USER_INFO");
            //创建USER_INFO表
            stmt.execute("CREATE TABLE USER_INFO(id VARCHAR(36) PRIMARY KEY,name VARCHAR(100),sex VARCHAR(4))");
            //新增
            stmt.executeUpdate("INSERT INTO USER_INFO VALUES('" + UUID.randomUUID()+ "','大日如来','男')");
            stmt.executeUpdate("INSERT INTO USER_INFO VALUES('" + UUID.randomUUID()+ "','青龙','男')");
            stmt.executeUpdate("INSERT INTO USER_INFO VALUES('" + UUID.randomUUID()+ "','白虎','男')");
            stmt.executeUpdate("INSERT INTO USER_INFO VALUES('" + UUID.randomUUID()+ "','朱雀','女')");
            stmt.executeUpdate("INSERT INTO USER_INFO VALUES('" + UUID.randomUUID()+ "','玄武','男')");
            stmt.executeUpdate("INSERT INTO USER_INFO VALUES('" + UUID.randomUUID()+ "','苍狼','男')");
            //删除
            stmt.executeUpdate("DELETE FROM USER_INFO WHERE name='大日如来'");
            //修改
            stmt.executeUpdate("UPDATE USER_INFO SET name='孤傲苍狼' WHERE name='苍狼'");
            //查询
            ResultSet rs = stmt.executeQuery("SELECT * FROM USER_INFO");
            //遍历结果集
            while (rs.next()) {
                System.out.println(rs.getString("id") + "," + rs.getString("name")+ "," + rs.getString("sex"));
            }
            //释放资源
            stmt.close();
            //关闭连接
            conn.close();
        }
}

 

运行结果如下:

注意:如果使用H2数据库的内存模式,那么我们创建的数据库和表都只是保存在内存中,一旦服务器重启,那么内存中的数据库和表就不存在了。

时间: 2024-12-22 06:00:17

Java在Web应用程序中如何使用嵌入式数据库H2的相关文章

在Visual Web应用程序中使用Java Persistence API

借助 NetBeans IDE 6.0 和 Visual Web 工具,您可以使用 Visual Web 数据提供程 序组件以及 Java Persistence API(JPA)来编写连接到数据库表的应用程序.建立了到 数据库表的连接之后,可以使用 Java Persistence API 执行数据库 CRUD 操作(即创建 .读取.更新和删除操作).在开发基于数据库的应用程序时,使用 Java Persistence API 能提供更高的灵活性. 本文是本系列文章的第 1 篇(共两篇),主要

WEB应用程序中的进度条

web|程序 WEB应用程序中的进度条 Julien Cheyssial 写作于2003/10/01 Joise.LI翻译并修改于2004-4-2 写在前面: 原文是我在需要使用进度条时找到的一篇文章,讲解详细并附有实例.我在原文的基础上加上了自己的修改:增加了线程处理并且将进度条的使用放到了子线程中处理.这是我第一次翻译文章,敬请各位指正.原文见于http://www.myblogroll.com/Articles/progressbar/,请对照参考. 谁说在WEB应用程序中不能使用进度条?

启用Web应用程序中的后退导航

用 Webflow Navigation Manager Framework 改善用户体验 Web 应用程序的导航与静态 Web 站点的导航有很大的不同.当在一个静态 Web 站点 中导航时,可以使用浏览器的后退(Back)和前进(Forward)按钮,从一个页面跳转到 另一个页面,或者将喜欢的页面保存为书签,以便随时返回到该页面.通过浏览器的后 退按钮,可以在 Web 站点中后退导航,而且浏览器可以放心地缓存 Web 页面,因为显 示的页面不必反映服务器端应用程序的当前状态. 然而,当在 We

Web应用程序中Resource Bundle技术概述

背景概述 世界经济日益全球化的同时,一个应用程序需要在全球范围内使用势在必然.传统的程序设计方法将可翻译信息如菜单按钮的标签,提示信息,帮助文档等文字信息硬编码在程序代码中,不能很好的适应全球化发展,程序的扩展性差,维护成本高.一个能支持全球化的应用程序,必须实现单一可执行的程序,动态地使用资源(Single Source Single Executable),图1 是两种模型的对比图. 图 1. 传统的程序模型和支持全球化程序模型 对于一个能支持全球化的应用程序来说: 一方面需要考虑的是用户的

Asp.Net在Web应用程序中执行计划任务(多线程)

asp.net|web|程序|多线程|执行 在业务复杂的应用程序中,有时候会要求一个或者多个任务在一定的时间或者一定的时间间隔内计划进行,比如定时备份或同步数据库,定时发送电子邮件等,我们称之为计划任务.实现计划任务的方法也有很多,可以采用SQLAgent执行存储过程来实现,也可以采用Windows任务调度程序来实现,也可以使用Windows服务来完成我们的计划任务,这些方法都是很好的解决方案.但是,对于Web应用程序来说,这些方法实现起来并不是很简单的,主机服务提供商或者不能直接提供这样的服务

将规则集嵌入到由公共云托管的Web应用程序中的架构和流程

在本系列的第 2 部分中,我们将介绍用于将规则集嵌入到由公共云托管的 Web 应用程序中的架构和流程. 本专栏面向 http://www.aliyun.com/zixun/aggregation/13387.html">WebSphere Operational Decision Management 开发人员,并假设读者能够从开发人员的角度较好地理解该产品.参阅 参考资料 部分,了解完成本专栏介绍的步骤需要具备的知识.在撰写本专栏时,我使用的产品版本为 WebSphere Operati

我在使用VS写asp.net,web应用程序中如何连sql server 接数据库

问题描述 我在使用VS写asp.net,web应用程序中如何连sql server 接数据库 10C 在web程序中我需要连接数据库,使用其中的数据.怎样才能用js与我的sql server2012连接,有没有具体的列子啊!新手求大神解答. 解决方案 用js与数据库连接还是第一次听说,你如果需要执行数据操作是需要后端语言的,Web应用在后台代码中可以用ADO.NET技术来进行数据操作.可以前台js 使用Ajax Post后者Get请求后端接口,后端进行数据库的增删改查.如果是服务器控件直接在事件

怎样才能做到在web应用程序中实行互传文件的功能,紧急!

问题描述 怎样才能做到在web应用程序中实行互传文件的功能,紧急!点击按钮之后实现fileupload控件的功能 解决方案 解决方案二:和FTP差不多?解决方案三:两个客户端互传?只能其中一个上传另一个下载,不能点对点,剩下就是服务器实现了.解决方案四:该回复于2009-05-15 11:14:37被版主删除解决方案五:问题问的好,但不能帮助你,不会解决方案六:点对点可以.因为有些Webim已经实现此功能.不过要自己做插件.要么就利用服务器,一个上传,另一个下载了.不过这样没什么意思,还不如通过

c# web应用程序中怎么运用jS文件

问题描述 web应用程序中怎么运用js文件, 解决方案 解决方案二:aspx文件中引入<scriptsrc="xxx.js"></script>