目錄
1. 下載H2數(shù)據(jù)庫(kù)
2. 在JavaWeb項(xiàng)目中使用H2
3. 在JavaWeb項(xiàng)目中嵌入H2
4. 向H2數(shù)據(jù)庫(kù)注冊(cè)自定義的數(shù)據(jù)庫(kù)函數(shù)
簡(jiǎn)介
優(yōu)勢(shì):
1. H2采用純Java編寫,因此不受平臺(tái)的限制。
2. H2只有一個(gè)jar文件谬墙,非常適合作為嵌入式數(shù)據(jù)庫(kù)(不需要安裝獨(dú)立的客戶端和服務(wù)器端)。
3. H2提供了一個(gè)十分方便的web控制臺(tái)用于操作和管理數(shù)據(jù)庫(kù)內(nèi)容。
1. 下載H2數(shù)據(jù)庫(kù)
- 下載H2數(shù)據(jù)庫(kù)
下載最新版本的H2數(shù)據(jù)庫(kù)(選擇Platform-IndependentZip),并解壓到指定目錄(如:/Users/cx/H2Database)
H2數(shù)據(jù)庫(kù)的目錄結(jié)構(gòu)說明
h2
|---bin
| |---h2-2.1.214.jar // H2數(shù)據(jù)庫(kù)的jar包(驅(qū)動(dòng)也在里面)
| |---h2.bat // Windows控制臺(tái)啟動(dòng)腳本
| |---h2.sh // Linux/MAC控制臺(tái)啟動(dòng)腳本
| |---h2w.bat // Windows控制臺(tái)啟動(dòng)腳本(不帶黑屏窗口)
|---docs // H2數(shù)據(jù)庫(kù)的幫助文檔(內(nèi)有H2數(shù)據(jù)庫(kù)的使用手冊(cè))
|---service // 通過wrapper包裝成服務(wù)浓若。
|---src // H2數(shù)據(jù)庫(kù)的源代碼
|---build.bat // Windows構(gòu)建腳本
|---build.sh // Linux構(gòu)建腳本
- 啟動(dòng)H2數(shù)據(jù)庫(kù)服務(wù)
在終端執(zhí)行:
cd /Users/cx/H2Database/h2/bin
sh h2.sh
在瀏覽器中訪問H2數(shù)據(jù)庫(kù)的WebConsole:http://localhost:8082
- 創(chuàng)建并連接數(shù)據(jù)庫(kù)、創(chuàng)建表
2. 在JavaWeb項(xiàng)目中使用H2
1. 創(chuàng)建Web項(xiàng)目(Dynamic Web Project)
2. 導(dǎo)入H2依賴包
將h2-xxx.jar復(fù)制到WEB-INF/lib目錄下
3. 以嵌入式(本地)連接方式連接H2數(shù)據(jù)庫(kù)(方式1)
默認(rèn)情況下只允許有一個(gè)客戶端連接到H2數(shù)據(jù)庫(kù)(有客戶端連接到H2數(shù)據(jù)庫(kù)之后倚评,此時(shí)數(shù)據(jù)庫(kù)文件就會(huì)被鎖定,其他客戶端無(wú)法再連接)馏予。
連接語(yǔ)法:jdbc:h2:[file:][<path>]<databaseName>
例:
jdbc:h2:~/test // 連接位于用戶目錄下的test數(shù)據(jù)庫(kù)
jdbc:h2:file:/data/sample
jdbc:h2:file:E:/H2/test(Windows系統(tǒng)下)
===》Test.java
package com.sst.cx;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
public class Test {
// 數(shù)據(jù)庫(kù)連接URL
private static final String JDBC_URL = "jdbc:h2:~/H2Database/h2/bin/test";
// 連接數(shù)據(jù)庫(kù)的用戶名
private static final String USER = "sa";
// 連接數(shù)據(jù)庫(kù)的密碼
private static final String PASSWORD = "密碼";
// 連接數(shù)據(jù)庫(kù)的驅(qū)動(dòng)類(H2數(shù)據(jù)庫(kù)提供)
private static final String DRIVER_CLASS="org.h2.Driver";
public static void main(String[] args) throws Exception {
// 加載H2數(shù)據(jù)庫(kù)驅(qū)動(dòng)
Class.forName(DRIVER_CLASS);
// 根據(jù)連接URL天梧,用戶名,密碼獲取數(shù)據(jù)庫(kù)連接
Connection conn = DriverManager.getConnection(JDBC_URL, USER, PASSWORD);
Statement stmt = conn.createStatement();
// 如果存在USERS表就先刪除USERS表
stmt.execute("DROP TABLE IF EXISTS USERS");
// 創(chuàng)建users表
stmt.execute("create table users("
+ " id int primary key,"
+ " name varchar(40),"
+ " password varchar(40))");
// 新增
stmt.executeUpdate("INSERT INTO users VALUES(1,'張三','12')");
stmt.executeUpdate("INSERT INTO users VALUES(2,'李四','34')");
stmt.executeUpdate("INSERT INTO users VALUES(3,'王五','56')");
stmt.executeUpdate("INSERT INTO users VALUES(4,'麻六','78')");
stmt.executeUpdate("INSERT INTO users VALUES(5,'鄒七','90')");
// 刪除
stmt.executeUpdate("DELETE FROM users WHERE name='張三'");
// 修改
stmt.executeUpdate("UPDATE users SET name='李二' WHERE name='李四'");
// 查詢
ResultSet rs = stmt.executeQuery("SELECT * FROM users");
// 遍歷結(jié)果集
while (rs.next()) {
System.out.println(rs.getString("id") + "," + rs.getString("name")+ "," + rs.getString("password"));
}
// 釋放資源
stmt.close();
// 關(guān)閉連接
conn.close();
}
}
3. 使用TCP/IP的服務(wù)器模式(遠(yuǎn)程連接)方式連接H2數(shù)據(jù)庫(kù)(方式2 推薦)
連接方式和其他數(shù)據(jù)庫(kù)類似(基于Service的形式進(jìn)行連接)霞丧,因此允許多個(gè)客戶端同時(shí)連接到H2數(shù)據(jù)庫(kù)呢岗。
連接語(yǔ)法:jdbc:h2:tcp://<server>[:<port>]/[<path>]<databaseName>
例:
jdbc:h2:tcp://localhost/~/test
===》Test2.java
package com.sst.cx;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
public class Test2 {
// 數(shù)據(jù)庫(kù)連接URL
private static final String JDBC_URL = "jdbc:h2:tcp://127.0.0.1/~/H2Database/h2/bin/test";
// 連接數(shù)據(jù)庫(kù)的用戶名
private static final String USER = "sa";
// 連接數(shù)據(jù)庫(kù)的密碼
private static final String PASSWORD = "密碼";
// 連接數(shù)據(jù)庫(kù)的驅(qū)動(dòng)類(由H2數(shù)據(jù)庫(kù)提供)
private static final String DRIVER_CLASS="org.h2.Driver";
public static void main(String[] args) throws Exception {
// 加載H2數(shù)據(jù)庫(kù)驅(qū)動(dòng)
Class.forName(DRIVER_CLASS);
// 根據(jù)連接URL,用戶名蛹尝,密碼獲取數(shù)據(jù)庫(kù)連接
Connection conn = DriverManager.getConnection(JDBC_URL, USER, PASSWORD);
Statement stmt = conn.createStatement();
//如果存在users表就先刪除users表
stmt.execute("DROP TABLE IF EXISTS USERS");
// 創(chuàng)建users表
stmt.execute("create table users("
+ " id int primary key,"
+ " name varchar(40),"
+ " password varchar(40))");
// 新增
stmt.executeUpdate("INSERT INTO users VALUES(1,'張三','12')");
stmt.executeUpdate("INSERT INTO users VALUES(2,'李四','34')");
stmt.executeUpdate("INSERT INTO users VALUES(3,'王五','56')");
stmt.executeUpdate("INSERT INTO users VALUES(4,'麻六','78')");
stmt.executeUpdate("INSERT INTO users VALUES(5,'鄒七','90')");
// 刪除
stmt.executeUpdate("DELETE FROM users WHERE name='張三'");
// 修改
stmt.executeUpdate("UPDATE users SET name='李二' WHERE name='李四'");
// 查詢
ResultSet rs = stmt.executeQuery("SELECT * FROM users");
// 遍歷結(jié)果集
while (rs.next()) {
System.out.println(rs.getString("id") + "," + rs.getString("name")+ "," + rs.getString("password"));
}
// 釋放資源
stmt.close();
// 關(guān)閉連接
conn.close();
}
}
3. 在JavaWeb項(xiàng)目中嵌入H2
1. 創(chuàng)建Web項(xiàng)目(Dynamic Web Project)
2. 導(dǎo)入依賴包
將h2-xxx.jar后豫、servlet-api.jar復(fù)制到WEB-INF/lib目錄下
3. 創(chuàng)建一個(gè)專門用于啟動(dòng)H2數(shù)據(jù)庫(kù)服務(wù)的監(jiān)聽器
===》H2DBServerStartListener.java
package com.sst.cx.web.listener;
import java.sql.SQLException;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import org.h2.tools.Server;
// 用于啟動(dòng)H2數(shù)據(jù)庫(kù)服務(wù)的Listener
public class H2DBServerStartListener implements ServletContextListener {
// H2數(shù)據(jù)庫(kù)服務(wù)器啟動(dòng)實(shí)例
private Server server;
// Web應(yīng)用初始化時(shí)啟動(dòng)H2數(shù)據(jù)庫(kù)
public void contextInitialized(ServletContextEvent sce) {
try {
System.out.println("正在啟動(dòng)h2數(shù)據(jù)庫(kù)...");
// 使用org.h2.tools.Server這個(gè)類創(chuàng)建一個(gè)H2數(shù)據(jù)庫(kù)的服務(wù)并啟動(dòng)服務(wù),由于沒有指定任何參數(shù)突那,那么H2數(shù)據(jù)庫(kù)啟動(dòng)時(shí)默認(rèn)占用的端口就是8082
server = Server.createTcpServer().start();
System.out.println("h2數(shù)據(jù)庫(kù)啟動(dòng)成功...");
} catch (SQLException e) {
System.out.println("啟動(dòng)h2數(shù)據(jù)庫(kù)出錯(cuò):" + e.toString());
e.printStackTrace();
throw new RuntimeException(e);
}
}
// Web應(yīng)用銷毀時(shí)停止H2數(shù)據(jù)庫(kù)
public void contextDestroyed(ServletContextEvent sce) {
if (this.server != null) {
// 停止H2數(shù)據(jù)庫(kù)
this.server.stop();
this.server = null;
}
}
}
4. 在web.xml文件中添加
<!-- 配置監(jiān)聽器:?jiǎn)?dòng)和停止H2數(shù)據(jù)庫(kù)服務(wù) -->
<listener>
<listener-class>com.sst.cx.web.listener.H2DBServerStartListener</listener-class>
</listener>
<!-- 配置用于訪問H2數(shù)據(jù)庫(kù)Console的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控制臺(tái)的訪問路徑 -->
<servlet-mapping>
<servlet-name>H2Console</servlet-name>
<url-pattern>/console/*</url-pattern>
</servlet-mapping>
5. 測(cè)試
部署到Tomcat挫酿,并啟動(dòng)Tomcat。
在瀏覽器中輸入http://localhost:8080/hello/console/ 可訪問H2的Web控制臺(tái)愕难。
4. 向H2數(shù)據(jù)庫(kù)注冊(cè)自定義的數(shù)據(jù)庫(kù)函數(shù)
1. 實(shí)現(xiàn)自定義數(shù)據(jù)庫(kù)函數(shù)
創(chuàng)建一個(gè)普通類早龟,創(chuàng)建一個(gè)public static修飾的方法并實(shí)現(xiàn)。
例:
public class Hello{
public static String hi(){
return "hello"; // 根據(jù)自身需求猫缭,編寫功能
}
}
2. 注冊(cè)到H2數(shù)據(jù)庫(kù)中(在H2的Web控制臺(tái)中執(zhí)行)
CREATE ALIAS [IF NOT EXISTS] newFunctionAliasName [DETERMINISTIC] FOR classAndMethodName
例:
CREATE ALIAS hello FOR "com.sst.cx.Hello.hi"
3. 測(cè)試
select hello()
例(一次性向H2數(shù)據(jù)庫(kù)注冊(cè)多個(gè)函數(shù))
===》1. H2DBFunctionExt.java(定義數(shù)據(jù)庫(kù)函數(shù))
package com.sst.cx;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.UUID;
public class Hello {
public static String hi(){
return "hello";
}
public static String my_uuid(){
return "com.sst.cx"+UUID.randomUUID().toString();
}
public static String now(){
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date date = new Date();
String dateStr = simpleDateFormat.format(date);
return dateStr;
}
public static String getIp(){
try {
InetAddress addr = InetAddress.getLocalHost();
// 獲得本機(jī)IP
return addr.getHostAddress();
} catch (UnknownHostException e) {
e.printStackTrace();
return "未知的IP地址";
}
}
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 "";
}
}
===》2. RegisterH2ExtFuncServlet.java(注冊(cè)數(shù)據(jù)庫(kù)函數(shù))
package com.sst.cx;
import java.sql.Connection;
import java.sql.Statement;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
public class RegisterH2ExtFuncServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
public void init() throws ServletException {
// 0拄衰、注冊(cè)hi函數(shù)的SQL語(yǔ)句
String sql0 = "CREATE ALIAS IF NOT EXISTS hello FOR \"com.sst.cx.H2DBFunctionExt.hi\"";
// 1、注冊(cè)u(píng)uid函數(shù)的SQL語(yǔ)句
String sql1 = "CREATE ALIAS IF NOT EXISTS my_uuid FOR \"com.sst.cx.H2DBFunctionExt.my_uuid\"";
// 2饵骨、注冊(cè)currentTime函數(shù)的SQL語(yǔ)句
String sql2 = "CREATE ALIAS IF NOT EXISTS currentTime FOR \"com.sst.cx.H2DBFunctionExt.now\"";
// 3、注冊(cè)IP函數(shù)的SQL語(yǔ)句
String sql3 = "CREATE ALIAS IF NOT EXISTS IP FOR \"com.sst.cx.H2DBFunctionExt.getIp\"";
// 4茫打、注冊(cè)date_format函數(shù)的SQL語(yǔ)句
String sql4 = "CREATE ALIAS IF NOT EXISTS date_format FOR \"com.sst.cx.H2DBFunctionExt.date_format\"";
Connection connection = null;
Statement stmt = null;
try {
// 獲取數(shù)據(jù)庫(kù)連接
connection = JdbcUtil.getConnection();
// 獲取Statement對(duì)象
stmt = connection.createStatement();
// 添加要執(zhí)行的SQL
stmt.addBatch(sql0);
stmt.addBatch(sql1);
stmt.addBatch(sql2);
stmt.addBatch(sql3);
stmt.addBatch(sql4);
// 批量執(zhí)行
stmt.executeBatch();
System.out.println("H2數(shù)據(jù)庫(kù)擴(kuò)展函數(shù)注冊(cè)成功居触!");
stmt.clearBatch();
} catch (Exception e) {
System.out.println("H2數(shù)據(jù)庫(kù)擴(kuò)展函數(shù)注冊(cè)失敗老赤!");
e.printStackTrace();
}finally{
try {
stmt.close();
connection.close();
} catch (Exception e2) {
e2.printStackTrace();
}
}
}
}
===》3. 在web.xml文件中轮洋,添加
<servlet>
<description>注冊(cè)H2數(shù)據(jù)庫(kù)的擴(kuò)展函數(shù)</description>
<servlet-name>RegisterH2DBExtFunction</servlet-name>
<servlet-class>com.sst.cx.RegisterH2ExtFuncServlet</servlet-class>
<!--
1、load-on-startup元素標(biāo)記容器是否在啟動(dòng)的時(shí)候就加載這個(gè)servlet(實(shí)例化并調(diào)用其init()方法)抬旺。
2弊予、它的值必須是一個(gè)整數(shù),表示servlet應(yīng)該被載入的順序
3开财、當(dāng)值為0或者大于0時(shí)汉柒,表示容器在應(yīng)用啟動(dòng)時(shí)就加載并初始化這個(gè)servlet;
4责鳍、當(dāng)值小于0或者沒有指定時(shí)碾褂,則表示容器在該servlet被選擇時(shí)才會(huì)去加載。
5历葛、正數(shù)的值越小正塌,該servlet的優(yōu)先級(jí)越高,應(yīng)用啟動(dòng)時(shí)就越先加載。
6乓诽、當(dāng)值相同時(shí)帜羊,容器就會(huì)自己選擇順序來加載。
所以鸠天,<load-on-startup>x</load-on-startup>讼育,中x的取值1,2粮宛,3窥淆,4,5代表的是優(yōu)先級(jí)巍杈,而非啟動(dòng)延遲時(shí)間忧饭。
-->
<load-on-startup>1</load-on-startup>
</servlet>
===》4. JdbcUtil.java(提供JDBC連接)
package com.sst.cx;
import java.io.InputStream;
import java.sql.Connection;
import java.util.Properties;
import org.h2.jdbcx.JdbcConnectionPool;
public class JdbcUtil {
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);
// 創(chuàng)建數(shù)據(jù)庫(kù)連接池
cp = JdbcConnectionPool.create(prop.getProperty("JDBC_URL"), prop.getProperty("USER"), prop.getProperty("PASSWORD"));
} catch (Exception e) {
System.out.println("連接池初始化異常");
e.printStackTrace();
}
}
public static Connection getConnection() throws Exception{
return cp.getConnection();
}
public static JdbcConnectionPool getCp() {
return cp;
}
}
===》5. 創(chuàng)建h2config.properties文件(src目錄下)
JDBC_URL=jdbc:h2:tcp://127.0.0.1/~/H2Database/h2/bin/test
USER=sa
PASSWORD=密碼