文档章节

嵌入式数据库H2学习总结(二)——在Web应用程序中使用H2数据库

小白的成长
 小白的成长
发布于 2017/05/23 10:43
字数 2098
阅读 53
收藏 0
H2

一、搭建测试环境和项目

1.1、搭建JavaWeb测试项目

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

  

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

  

1.2、开启H2数据库

  进入到h2\bin目录,如下图所示:

  

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

  

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

二、在Java中操作H2数据库

2.1、以嵌入式(本地)连接方式连接H2数据库

  这种连接方式默认情况下只允许有一个客户端连接到H2数据库,有客户端连接到H2数据库之后,此时数据库文件就会被锁定,那么其他客户端就无法再连接了。

  连接语法:jdbc:h2:[file:][<path>]<databaseName>

  例如:
    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://<server>[:<port>]/[<path>]<databaseName>
  范例: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数据库的内存模式,那么我们创建的数据库和表都只是保存在内存中,一旦服务器重启,那么内存中的数据库和表就不存在了。

© 著作权归作者所有

小白的成长
粉丝 4
博文 39
码字总数 30248
作品 0
深圳
程序员
私信 提问
Java嵌入式数据库H2学习总结(一)——H2数据库入门

一、H2数据库介绍   常用的开源数据库有:H2,Derby,HSQLDB,MySQL,PostgreSQL。其中H2和HSQLDB类似,十分适合作为嵌入式数据库使用,而其它的数据库大部分都需要安装独立的客户端和服务...

guicaizhou
2016/07/08
0
0
SpringBoot实战(四)之使用JDBC和Spring访问数据库

这里演示的是h2databse示例,所以简单的介绍普及下h2database相关知识 H2数据库是一个开源的关系型数据库。 H2是一个嵌入式数据库引擎,采用java语言编写,不受平台的限制,同时H2提供了一个...

youcongtech
2018/08/03
0
0
能够可视化访问和查看H2数据库的工具

最近在学习和了解SpringBoot的微服务开发框架,其中SpringBoot默认的持久化数据库就是H2数据库。 稍微科普一下,h2 database 是一个开源免费的嵌入式(Embedding) Java SQL数据库。下载地址:...

chancein007
2017/01/11
0
0
H2介绍 – Java嵌入式数据库

H2是一个用Java开发的嵌入式数据库,这里指的嵌入式不是手持设备之类的,而是H2数据库作为一个类库,直接嵌入到上层的应用程序中,与应用运行在同一个进程中。 最大的优势在于可以同应用程序...

Mr&Cheng
2013/01/20
756
0
mybatis学习笔记

mybatis是一个ORM框架,因为activiti使用了mybatis,所以学习下; mybatis单独运行可以不依靠任何框架,也不需要tomcat; 一,步骤概要: 1,手动创建数据库表,创建一个USER表; 2,创建核心...

安世博
2014/10/17
262
3

没有更多内容

加载失败,请刷新页面

加载更多

mysql-connector-java升级到8.0后保存时间到数据库出现了时差

在一个新项目中用到了新版的mysql jdbc 驱动 <dependency>     <groupId>mysql</groupId>     <artifactId>mysql-connector-java</artifactId>     <version>8.0.18</version> ......

ValSong
今天
5
0
Spring Boot 如何部署到 Linux 中的服务

打包完成后的 Spring Boot 程序如何部署到 Linux 上的服务? 你可以参考官方的有关部署 Spring Boot 为 Linux 服务的文档。 文档链接如下: https://docs.ossez.com/spring-boot-docs/docs/r...

honeymoose
今天
6
0
Spring Boot 2 实战:使用 Spring Boot Admin 监控你的应用

1. 前言 生产上对 Web 应用 的监控是十分必要的。我们可以近乎实时来对应用的健康、性能等其他指标进行监控来及时应对一些突发情况。避免一些故障的发生。对于 Spring Boot 应用来说我们可以...

码农小胖哥
今天
9
0
ZetCode 教程翻译计划正式启动 | ApacheCN

原文:ZetCode 协议:CC BY-NC-SA 4.0 欢迎任何人参与和完善:一个人可以走的很快,但是一群人却可以走的更远。 ApacheCN 学习资源 贡献指南 本项目需要校对,欢迎大家提交 Pull Request。 ...

ApacheCN_飞龙
今天
5
0
CSS定位

CSS定位 relative相对定位 absolute绝对定位 fixed和sticky及zIndex relative相对定位 position特性:css position属性用于指定一个元素在文档中的定位方式。top、right、bottom、left属性则...

studywin
今天
9
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部