Java嵌入式數據庫H2學習總結(二)——在Web應用程序中使用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)

  編寫測試代碼,如下:

複製代碼

 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://<server>[:<port>]/[<path>]<databaseName>
  範例: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數據庫的全部內容。

發佈了7 篇原創文章 · 獲贊 12 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章