一椎椰、H2簡介
??1、H2是一個(gè)用Java開發(fā)的嵌入式數(shù)據(jù)庫令花,它本身只是一個(gè)類庫阻桅,可以直接嵌入到應(yīng)用項(xiàng)目中。
??H2最大的用途在于可以同應(yīng)用程序打包在一起發(fā)布兼都,這樣可以非常方便地存儲少量結(jié)構(gòu)化數(shù)據(jù)嫂沉。
??它的另一個(gè)用途是用于單元測試。啟動(dòng)速度快扮碧,而且可以關(guān)閉持久化功能趟章,每一個(gè)用例執(zhí)行完隨即還原到初始狀態(tài)。
??H2的第三個(gè)用處是作為緩存慎王,作為NoSQL的一個(gè)補(bǔ)充蚓土。當(dāng)某些場景下數(shù)據(jù)模型必須為關(guān)系型,可以拿它當(dāng)Memcached使赖淤,作為后端MySQL/Oracle的一個(gè)緩沖層蜀漆,緩存一些不經(jīng)常變化但需要頻繁訪問的數(shù)據(jù),比如字典表咱旱、權(quán)限表确丢。不過這樣系統(tǒng)架構(gòu)就會比較復(fù)雜了绷耍。
??2、H2的產(chǎn)品優(yōu)勢:
??純Java編寫鲜侥,不受平臺的限制褂始;
??只有一個(gè)jar文件,適合作為嵌入式數(shù)據(jù)庫使用描函;
??h2提供了一個(gè)十分方便的web控制臺用于操作和管理數(shù)據(jù)庫內(nèi)容;
??功能完整舀寓,支持標(biāo)準(zhǔn)SQL和JDBC。麻雀雖小五臟俱全基公;
??支持內(nèi)嵌模式、服務(wù)器模式和集群轰豆。
二胰伍、下載和安裝
??1、下載骂租,H2數(shù)據(jù)庫下載地址:http://www.h2database.com/html/download.html。
??解壓縮后的目錄結(jié)構(gòu):
????h2
????|---bin
????|??|---h2-1.4.199.jar????// H2數(shù)據(jù)庫的jar包(驅(qū)動(dòng)也在里面)
????|??|---h2.bat????// Windows控制臺啟動(dòng)腳本
????|??|---h2.sh????// Linux控制臺啟動(dòng)腳本
????|??|---h2w.bat????// Windows控制臺啟動(dòng)腳本(不帶黑屏窗口)
????|---docs????// H2數(shù)據(jù)庫的幫助文檔(內(nèi)有H2數(shù)據(jù)庫的使用手冊)
????|---service????// 通過wrapper包裝成服務(wù)渗饮。
????|---src????// H2數(shù)據(jù)庫的源代碼
????|---build.bat????// windows構(gòu)建腳本
????|---build.sh????// linux構(gòu)建腳本
??此時(shí)就算“安裝”完成了。
三宿刮、運(yùn)行模式與運(yùn)行方式
??(一)運(yùn)行模式
??H2有三種運(yùn)行模式互站。
??1、內(nèi)嵌模式(Embedded Mode)
??內(nèi)嵌模式下僵缺,應(yīng)用和數(shù)據(jù)庫同在一個(gè)JVM中磕潮,通過JDBC進(jìn)行連接翠胰∽愿可持久化,但同時(shí)只能一個(gè)客戶端連接锻狗。內(nèi)嵌模式性能會比較好。
??2、服務(wù)器模式(Server Mode):使用服務(wù)器模式和內(nèi)嵌模式一樣脚囊,只不過它可以跑在另一個(gè)進(jìn)程里桐磁。
??3讲岁、混合模式
??第一個(gè)應(yīng)用以內(nèi)嵌模式啟動(dòng)它,對于后面的應(yīng)用來說它是服務(wù)器模式跑著的缓艳。混合模式是內(nèi)嵌模式和服務(wù)器模式的組合衙吩。第一個(gè)應(yīng)用通過內(nèi)嵌模式與數(shù)據(jù)庫建立連接溪窒,同時(shí)也作為一個(gè)服務(wù)器啟動(dòng),于是另外的應(yīng)用(運(yùn)行在不同的進(jìn)程或是虛擬機(jī)上)可以同時(shí)訪問同樣的數(shù)據(jù)澈蚌。第一個(gè)應(yīng)用的本地連接與嵌入式模式的連接性能一樣的快,而其它連接理論上會略慢浮禾。
??(二)連接方式
??1份汗、以嵌入式(本地)連接方式連接H2數(shù)據(jù)庫
??這種連接方式默認(rèn)情況下只允許有一個(gè)客戶端連接到H2數(shù)據(jù)庫,有客戶端連接到H2數(shù)據(jù)庫之后杯活,此時(shí)數(shù)據(jù)庫文件就會被鎖定,那么其他客戶端就無法再連接了卷扮。
??連接語法:jdbc:h2:[file:][<path>]<databaseName>
??例如:
????jdbc:h2:~/test????//?連接位于用戶目錄下的test數(shù)據(jù)庫
????jdbc:h2:file:/data/sample
????jdbc:h2:file:E:/H2/gacl(Windows only)
??2、使用TCP/IP的服務(wù)器模式(遠(yuǎn)程連接)方式連接H2數(shù)據(jù)庫(推薦)
??這種連接方式就和其他數(shù)據(jù)庫類似了晤锹,是基于Service的形式進(jìn)行連接的彤委,因此允許多個(gè)客戶端同時(shí)連接到H2數(shù)據(jù)庫。
??連接語法:jdbc:h2:tcp://<server>[:<port>]/[<path>]<databaseName>
??范例:jdbc:h2:tcp://localhost/~/test
??3、H2數(shù)據(jù)庫的內(nèi)存模式
??(1)封断、H2數(shù)據(jù)庫被稱為內(nèi)存數(shù)據(jù)庫舶担,因?yàn)樗С衷趦?nèi)存中創(chuàng)建數(shù)據(jù)庫和表。
??(2)衣陶、注意:如果使用H2數(shù)據(jù)庫的內(nèi)存模式,那么我們創(chuàng)建的數(shù)據(jù)庫和表都只是保存在內(nèi)存中教沾,一旦服務(wù)器重啟译断,那么內(nèi)存中的數(shù)據(jù)庫和表就不存在了。
四堪唐、實(shí)例
1该贾、使用Maven項(xiàng)目的依賴。
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
2杨蛋、H2數(shù)據(jù)庫的操作與mysql的類似。
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
/**
* @Description: 內(nèi)嵌數(shù)據(jù)庫H2的使用
* @author: zxt
* @time: 2019年6月4日 下午3:30:13
*/
public class H2Test {
/**
* 以嵌入式(本地)連接方式連接H2數(shù)據(jù)庫
*/
private static final String JDBC_URL = "jdbc:h2:E:/Java/H2Test/user";
/**
* 使用TCP/IP的服務(wù)器模式(遠(yuǎn)程連接)方式連接H2數(shù)據(jù)庫(推薦)
*/
// private static final String JDBC_URL = "jdbc:h2:tcp://10.35.14.122/C:/H2/user";
private static final String USER = "root";
private static final String PASSWORD = "root";
private static final String DRIVER_CLASS = "org.h2.Driver";
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
Class.forName(DRIVER_CLASS);
Connection conn = DriverManager.getConnection(JDBC_URL, USER, PASSWORD);
Statement statement = conn.createStatement();
statement.execute("DROP TABLE IF EXISTS USER_INF");
statement.execute("CREATE TABLE USER_INF(id INTEGER PRIMARY KEY, name VARCHAR(100), sex VARCHAR(2))");
statement.executeUpdate("INSERT INTO USER_INF VALUES(1, 'tom', '男') ");
statement.executeUpdate("INSERT INTO USER_INF VALUES(2, 'jack', '女') ");
statement.executeUpdate("INSERT INTO USER_INF VALUES(3, 'marry', '男') ");
statement.executeUpdate("INSERT INTO USER_INF VALUES(4, 'lucy', '男') ");
ResultSet resultSet = statement.executeQuery("select * from USER_INF");
while (resultSet.next()) {
System.out.println(
resultSet.getInt("id") + ", " + resultSet.getString("name") + ", " + resultSet.getString("sex"));
}
statement.close();
conn.close();
}
}