Hibernate 框架

Hibernate是一個開放源代碼]的對象關(guān)系映射框架,它對JDBC進(jìn)行了非常輕量級的對象封裝,它將POJO與數(shù)據(jù)庫表建立映射關(guān)系,是一個全自動的orm框架,hibernate可以自動生成SQL語句,自動執(zhí)行,使得Java程序員可以隨心所欲的使用對象編程思維來操縱數(shù)據(jù)庫。

Hibernate可以應(yīng)用在任何使用JDBC的場合,既可以在Java的客戶端程序使用,也可以在Servlet/JSP的Web應(yīng)用中使用,最具革命意義的是,Hibernate可以在應(yīng)用EJB的JavaEE架構(gòu)中取代CMP,完成數(shù)據(jù)持久化的重任。

Hibernate 中只需要通過“方言”的形式指定當(dāng)前使用的數(shù)據(jù)庫,就可以根據(jù)底層數(shù)據(jù)庫的實際情況生成適合的 SQL 語句。因此在使用 Hibernate 連接數(shù)據(jù)庫時,我們主要關(guān)注的配置就是數(shù)據(jù)庫方言這個參數(shù)。

Hibernate 使用 HGDB,只需要將“方言”這個配置參數(shù),改為 HGDB 方言即可。

開發(fā)環(huán)境搭建

軟件 版本
HGDB 安全版V4、企業(yè)版v5及以上版本
JDK 1.6、1.7、1.8
Java IDE Eclipse、IntelliJ IDEA

HGDB 針對 Hibernate 框架,封裝了 HGDB 方言包,現(xiàn)有的 Hibernate HGDB方言包支持的 Hibernate 版本,如下圖所示:

image-20220418151105678

Hibernate HGDB 方言包的說明,如下:

使用說明
HGDB 方言包是用于使用 Hibernate 開發(fā)提供支持的,該方言包使用依賴hibernate-core,因此需要應(yīng)用程序中已經(jīng)添加了相關(guān)的依賴包后才能使用。HGDB 方言包使用配置:org.hibernate.dialect.HgdbDialect

版本說明
HGDB 方言包使用依賴 hibernate-core,所以方言包的版本需要與hibernate-core 的版本對應(yīng),對應(yīng)規(guī)則為:HGDB 方言包 jar 包名字末尾的編號即是對應(yīng)的 hibernate-core 的版本號。

例:hgdb-hibernate-dialect-5.4.0.jar,需要對應(yīng)使用 hibernate-core 的 5.4.0 版本。

編譯環(huán)境說明

HGDB 的所有方言包均使用 jdk1.6 進(jìn)行編譯,所以需要在 jdk1.6 或以上的環(huán)境中使用。如果使用的 hibernate 版本在 HGDB 方言包的版本中不存在,請修改一下項目的 hibernate 版本,只要 hibernate 的大版本號一致,基本就沒有問題。

Hibernate引入 HGDB 方言包

以maven 倉庫方式為例:

mvn install:install-file -Dfile=C:\***\hgdb-hibernate-dialect-4.3.11.jar -DgroupId=highgo -DartifactId=hgdb-hibernate-dialect -Dversion=4.3.11 -Dpackaging=jar

## C:\***\hgdb-hibernate-dialect-4.3.11.jar 為本地絕對路徑

執(zhí)行結(jié)果,如下:

image-20220418152525445

示例項目

結(jié)構(gòu)圖如下:

image-20220516191541275

主要文件介紹

pom.xml:添加依賴(僅為片段部分)

<!-- hibernate配置-->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>4.3.11.Final</version>
</dependency>
<!-- HGDB的方言包-->
<dependency>
<groupId>highgo</groupId>
<artifactId>hgdb-hibernate-dialect</artifactId>
<version>4.3.11</version>
</dependency>
<!-- HGDB jdbc-->
<dependency>
<groupId>highgo</groupId>
<artifactId>highgo</artifactId>
<version>5.0-42</version>
</dependency>

hibernate.cfg.xml:Hibernate的核心配置文件,主要用來描述Hibernate的相關(guān)配置

<hibernate-configuration>
<!--構(gòu)造數(shù)據(jù)庫的連接工廠-->
<session-factory>
<!-- 配置關(guān)于數(shù)據(jù)庫連接信息 driverClass url username password僅為參考 -->
<property name="hibernate.connection.driver_class"><>com.highgo.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:highgo://localhost:5866/hibernateTest</property>
<property name="hibernate.connection.username">test</property>
<property name="hibernate.connection.password">test</property>
<!-- 可以將向數(shù)據(jù)庫發(fā)送的sql顯示出來 -->
<property name="hibernate.show_sql">true</property>
<!-- 格式化sql -->
<property name="hibernate.format_sql">true</property>
<!-- hibernate的方言,修改為 HGDB的方言包 -->
<property name="hibernate.dialect">org.hibernate.dialect.HgdbDialect</property>
<!-- 配置hibernate的映射文件所在位置 -->
<mapping resource="com/highgo/entitty/User.hbm.xml" />
</session-factory>
</hibernate-configuration>

User.hbm.xml:映射文件

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping
package="com.highgo.entity">

<class name="User" >
<id name="id">
<generator class="native"/>
</id>
<property name="name"/>
<property name="birthday"/>

</class>

</hibernate-mapping>

User.java:實體bean

public class User {
private int id;
private String name;
private Date birthday;

public int getId() {
return id;
}

public String getName() {
return name;
}

public Date getBirthday() {
return birthday;
}

public void setId(int id) {
this.id = id;
}

public void setName(String name) {
this.name = name;
}

public void setBirthday(Date birthday) {
this.birthday = birthday;
}

@Override
public String toString() {
return "User [id=" + id + ", name=" + name + ", birthday=" + birthday
+ "]";
}
}

MainTest.java:測試類

public class MainTest {
public static void main(String[] args) {
try {
Configuration conf=new Configuration();
SessionFactory sessionFactory= conf.configure().buildSessionFactory();
Session session=sessionFactory.openSession();
Transaction tx=session.beginTransaction();
User user=new User() ;
user.setName("張三");
user.setBirthday(new Date());
session.save(user);
tx.commit();
session.close();
//獲取數(shù)據(jù)集合
Transaction tx1=session.beginTransaction();
Criteria criteria =session.createCriteria(User.class);
List<User> list = criteria.list();
//使用forEach遍歷集合
for (User userEntity : list) {
System.out.println(userEntity);
}
tx1.commit();
} catch (Exception e) {
e.printStackTrace();
}
}
}

執(zhí)行結(jié)果:

image-20220418172933992

image-20220418173905608

注意事項

Hibernate主鍵生成策略

Hibernate要求實體類里面有一個屬性作為唯一值,對應(yīng)表主鍵,提供了多種主鍵的生成方式,具體有哪些以下做簡單介紹。

一、在映射配置文件中指定主鍵生成策略

<class name="User"  table="test_user">
<id name="id">
<generator class="native"/>
</id>
<property name="name"/>
<property name="birthday"/>
</class>

二、常見的主鍵生成策略

策略名稱 說明
Assigned Assigned方式由用戶生成主鍵值,并且要在save()之前指定否則會拋出異常。
特點:主鍵的生成值完全由用戶決定,與底層數(shù)據(jù)庫無關(guān)。用戶需要維護主鍵值,在調(diào)用session.save()之前要指定主鍵值。
Hilo Hilo使用高低位算法生成主鍵,高低位算法使用一個高位值和一個低位值,然后把算法得到的兩個值拼接起來作為數(shù)據(jù)庫中的唯一主鍵。Hilo方式需要額外的數(shù)據(jù)庫表和字段提供高位值來源。默認(rèn)情況下使用的表是hibernate_unique_key,默認(rèn)字段叫作next_hi。next_hi必須有一條記錄否則會出現(xiàn)錯誤。
特點:需要額外的數(shù)據(jù)庫表的支持,能保證同一個數(shù)據(jù)庫中主鍵的唯一性,但不能保證多個數(shù)據(jù)庫之間主鍵的唯一性。Hilo主鍵生成方式由Hibernate 維護,所以Hilo方式與底層數(shù)據(jù)庫無關(guān),但不應(yīng)該手動修改hi/lo算法使用的表的值,否則會引起主鍵重復(fù)的異常。
Increment Increment方式對主鍵值采取自動增長的方式生成新的主鍵值,但要求底層數(shù)據(jù)庫的主鍵類型為long,int等數(shù)值型。主鍵按數(shù)值順序遞增,增量為1。
特點:由Hibernate本身維護,適用于所有的數(shù)據(jù)庫,不適合多進(jìn)程并發(fā)更新數(shù)據(jù)庫,適合單一進(jìn)程訪問數(shù)據(jù)庫。不能用于群集環(huán)境。
Identity Identity方式根據(jù)底層數(shù)據(jù)庫,來支持自動增長,不同的數(shù)據(jù)庫用不同的主鍵增長方式。
特點:與底層數(shù)據(jù)庫有關(guān),要求數(shù)據(jù)庫支持Identity,如MySQl中是auto_increment, SQL Server 中是Identity,支持的數(shù)據(jù)庫有MySql、SQL Server、DB2、Sybase和HypersonicSQL。 Identity無需Hibernate和用戶的干涉,使用較為方便,但不便于在不同的數(shù)據(jù)庫之間移植程序。
Sequence Sequence需要底層數(shù)據(jù)庫支持Sequence方式,例如Oracle數(shù)據(jù)庫等
特點:需要底層數(shù)據(jù)庫的支持序列,支持序列的數(shù)據(jù)庫有DB2、PostgreSql、Oracle、SAPDb等在不同數(shù)據(jù)庫之間移植程序,特別從支持序列的數(shù)據(jù)庫移植到不支持序列的數(shù)據(jù)庫需要修改配置文件。
Native Native主鍵生成方式會根據(jù)不同的底層數(shù)據(jù)庫自動選擇Identity、Sequence、Hilo主鍵生成方式
特點:根據(jù)不同的底層數(shù)據(jù)庫采用不同的主鍵生成方式。由于Hibernate會根據(jù)底層數(shù)據(jù)庫采用不同的映射方式,因此便于程序移植,項目中如果用到多個數(shù)據(jù)庫時,可以使用這種方式。
UUID UUID使用128位UUID算法生成主鍵,能夠保證網(wǎng)絡(luò)環(huán)境下的主鍵唯一性,也就能夠保證在不同數(shù)據(jù)庫及不同服務(wù)器下主鍵的唯一性。
特點:能夠保證數(shù)據(jù)庫中的主鍵唯一性,生成的主鍵占用比較多的存貯空間

三、常見問題

遇到的問題:項目有mysql遷移到HGD環(huán)境時,提示ERROR: relation "HIBERNATE_SEQUENCE" does not exist

經(jīng)查證,Hibernate中的實體類使用native方式生成主鍵時,native是由Hibernate根據(jù)使用的數(shù)據(jù)庫自行判斷采用identity、hilo、sequence其中一種作為主鍵生成方式。而HGDB數(shù)據(jù)庫沒有類似的自增類型,因此需要手動創(chuàng)建一個名稱為hibernate_sequence的序列做支持。

create sequence HIBERNATE_SEQUENCE
minvalue 1
maxvalue 9999999999999999
start with 1
increment by 1
cache 20;