hibernate概述
hibernate是一個java的全自動ORM框架,它可以自動生成SQL語句、自動建表、自動執行,使用者可以不使用SQL完成資料的CRUD操作,同時它也是基於JPA規則的一種實現方式
建庫建表
在mysql資料庫中建立測試庫和表
-- 建庫
CREATE DATABASE `hibernate-test`;
-- 建表
CREATE TABLE `hibernate-test`.`h_user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`password` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
-- 插入資料
INSERT INTO h_user ( username, PASSWORD )
VALUES
( 'zhangsan', '123' );
INSERT INTO h_user ( username, PASSWORD )
VALUES
( 'lisi', '321' );
建立專案
本例項全程使用idea進行,並使用maven匯入依賴jar包
匯入依賴
在maven的pom檔案中加入hibernate的核心依賴包,為了方便使用模型,這裡我還匯入了lombok包,用於簡寫getter、setter等實體類方法
<dependencies>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.4.18.Final</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.48</version>
</dependency>
</dependencies>
編寫對映資料庫的物件模型實體
@Data
public class User {
private Integer id;
private String username;
private String password;
}
建立hibernate配置檔案
核心配置檔案
hibernate核心配置檔案預設命名為hibernate.cfg.xml
, 檔案的預設路徑是在類目錄下,這裡我放在resources資料夾下
.cfg : configuration
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<!-- 資料庫連線基本配置資訊 必填-->
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/hibernate-test?serverTimezone=GMT%2B8</property>
<!-- 資料庫方言:指定使用的資料庫種類 -->
<property name="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</property>
<!-- 是否顯示sql程式碼,用於在控制檯輸出執行的SQL語句 可選-->
<property name="hibernate.show_sql">true</property>
<!-- 格式化SQL,美化SQL語句輸出 可選-->
<property name="hibernate.format_sql">true</property>
<!-- 自動生成表策略
update: 若存在表則不生成表
create: 不管存在不存在都重新建立
-->
<property name="hibernate.hbm2ddl.auto">update</property>
<!-- 指定對映配置檔案的位置-->
<mapping resource="com/welisit/hibernate/demo/model/User.hbm.xml" />
</session-factory>
</hibernate-configuration>
物件關係對映配置檔案
對映配置檔案預設命名使用[實體類名].hbm.xml,檔案的預設路徑放在與實體類的同個目錄下,這裡我的對映配置檔名為User.hbm.xml
.hbm: hibernate mapper
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<!-- 配置表與實體物件的關係 -->
<hibernate-mapping>
<!-- name: 實體類的全類名
table: 表名
-->
<class name="com.welisit.hibernate.demo.model.User" table="h_user">
<id name="id" column="id">
<!-- 主鍵生成方式
native:使用資料庫設定的主鍵生成方式
-->
<generator class="native"/>
</id>
<property name="username" column="username"/>
<property name="password" column="password"/>
</class>
</hibernate-mapping>
測試
增加記錄
public void testInsert() {
// 建立hibernate核心配置檔案物件
Configuration configuration = new Configuration();
Configuration configure = configuration.configure();
// 建立能夠構建session的sessionfactory
SessionFactory sessionFactory = configure.buildSessionFactory();
// 一個session相當於一個連線, 通過session物件開啟事務
Session session = sessionFactory.openSession();
Transaction transaction = session.beginTransaction();
// 建立對映物件模型
User user = new User();
user.setPassword("312");
user.setUsername("aaa");
// 儲存物件
session.save(user);
// 提交事務
transaction.commit();
// 關閉會話
session.close();
// 關閉session工廠
sessionFactory.close();
}
執行上面的程式碼我們發現有報錯,內容大概是mapping對映檔案找不到
// 報錯資訊
org.hibernate.boot.MappingNotFoundException: Mapping (RESOURCE) not found : com/welisit/hibernate/demo/model/User.hbm.xml : origin(
...
通過檢視編譯輸出檔案發現原來在java資料夾中的沒有User.hbm.xml
,因為maven專案中,預設java目錄中除了生成編譯後的.class檔案是不會生成其他型別的檔案的。
解決方法:
方式一:直接將User.hbm.xml
檔案複製到輸出檔案目錄中即可
方式二:修改maven的pom檔案中的編譯打包配置
<!-- 專案打包時會將java目錄中的*.xml檔案也進行打包 -->
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
</build>
通過檢視configure方法原始碼,可以看出預設hibernate核心配置檔名就是hibernate.cfg.xml
刪除、修改
修改和刪除需要開啟事務才能進行
public void testUpdate() {
Session session = sessionFactory.openSession();
// 獲取修改的物件
User user = session.get(User.class, 1);
// 修改物件值
user.setUsername("abc");
// 更新需要開啟事務
Transaction transaction = session.beginTransaction();
session.update(user);
transaction.commit();
}
public void testRemove() {
Session session = sessionFactory.openSession();
// 獲取修改的物件
User user = session.get(User.class, 1);
Transaction transaction = session.beginTransaction();
// 刪除物件值
session.remove(user);
transaction.commit();
}
查詢
通過主鍵查詢
hibernate原生的session物件提供了通過物件主鍵查詢的方法
- get(javaBean.class, int id); 通過傳入的id進行查詢
- load(javaBean.class, int id); 同上,但這是懶載入
@Test
public void queryById() {
Session session = sessionFactory.openSession();
User user = session.load(User.class, 2);
System.out.println("懶載入執行完畢...");
System.out.println(user);
}
輸出結果
HQL查詢
簡介
HQL是Hibernate Query Language的縮寫,提供更加豐富靈活、更為強大的查詢能力;HQL更接近SQL語句查詢語法,它是對查詢條件進行了物件導向封裝。
示例
@Test
public void testHQL() {
// 使用hql語句查詢
Session session = sessionFactory.openSession();
// User類名在對映配置檔案的hibernate-mapping標籤配置了報名就可以在此不加包名
// ?1 指定佔位符的索引數為1
String hql = "from User where username = ?1";
// 引數也可以使用指定名稱
// String hql2 = "from User where username = :name"
Query<User> query = session.createQuery(hql, User.class);
query.setParameter(1, "aaa");
// query.setParameter("name", "aaa");
// 獲取單個返回結果值
User user = query.getSingleResult();
System.out.println(user);
}
@Test
public void testHQL2() {
// 使用hql語句查詢
Session session = sessionFactory.openSession();
// User類名在對映配置檔案的hibernate-mapping標籤配置了報名就可以在此不加包名
// ?1 指定佔位符的索引數為1
String hql1 = "from User where username = ?1";
Query<User> query = session.createQuery(hql1, User.class);
query.setParameter(1, "aaa");
// 查詢結果為多個值時使用getSingleResult會怎樣? 會報錯:
// javax.persistence.NonUniqueResultException: query did not return a unique result: 2
// getSingleResult實際呼叫的就是this.uniqueResult()
User user = query.getSingleResult();
System.out.println(user);
}
分頁查詢示例
@Test
public void testHQLPage() {
// 使用hql語句分頁查詢
Session session = sessionFactory.openSession();
String hql = "from User";
Query<User> query = session.createQuery(hql, User.class);
query.setFirstResult(0); // 從第幾條開始查詢
query.setMaxResults(2); // 每次查詢顯示幾條
List<User> userList = query.list();
userList.forEach(System.out::println);
}
輸出結果:
SQL查詢
hibernate也支援原生SQL來進行查詢
示例
@Test
public void testSQLQuery() {
// 原生SQL查詢
Session session = sessionFactory.openSession();
String sql = "select * from h_user";
// 建立sql查詢物件
NativeQuery sqlQuery = session.createSQLQuery(sql);
// 指定結果集封裝到哪個物件
sqlQuery.addEntity(User.class);
List list = sqlQuery.list();
list.forEach(System.out::println);
}
QBC查詢
曾經我一直幻想著什麼時候可以不使用SQL就能對資料庫進行增刪改查操作,這樣就能少學一點東西了。現在QBC出現了,就是和我幻想的一樣,不需要寫一條語句就能對資料庫完成各種CRUD操作,方便省事、節省寫sql時間,讓更多時間用在業務的邏輯開發中而不是這種簡單的CRUD程式碼中。
QBC: query by Criteria 【Criteria】條件、標準
使用步驟
QBC查詢是通過建立查詢物件對資料物件進行操作,首先第一步就是建立查詢物件
Criteria criteria = session.createCriteria(User.class)
使用Restrictions
構建條件,通過查詢物件設定查詢條件,最後得出結果
@Test
public void testQBCQuery() {
// QBC查詢
Session session = sessionFactory.openSession();
Criteria criteria = session.createCriteria(User.class);
criteria.add(Restrictions.eq("username", "aaa"));
Object o = criteria.uniqueResult();
System.out.println(o);
}
聚合查詢
@Test
public void testQBCQuery2() {
// QBC聚合查詢
Session session = sessionFactory.openSession();
Criteria criteria = session.createCriteria(User.class);
criteria.setProjection(Projections.count("id"));
Object o = criteria.uniqueResult();
System.out.println(o);
}
hibernate對映檔案詳解
hibernate-mapping
<!-- 配置表和實體類的對映關係 -->
<hibernate-mapping package="對映類所在的包">
package屬性: 指定實體類所在的包,凡是需要填寫包名的地方,使用這個之後,都可以省略,只寫類名
class
配置資料庫表與類的對應的關係
<class name="com.welisit.hibernate.demo.model.User" table="h_user">
- name: 完整類名
- table: 資料庫表名
class 標籤內部包含兩部分:id
和 property
id
配置主鍵對映的屬性
-
name:填寫主鍵對應屬性名
-
column:填寫表中主鍵列名
-
type(可選):填寫列(屬性)的型別.hibernate會自動檢測實體的屬性型別.
每個型別有三種填法: java型別|hibernate型別|資料庫型別
-
not-null(可選):配置該屬性(列)是否不能為空. 預設值:false
-
length(可選):配置資料庫中列的長度. 預設值:使用資料庫型別的最大長度
id標籤內部包含 generator
標籤
generator
元件生成策略
<generator class="native"/>
class屬性的幾個可選值
-
identity: 由資料庫來維護,hiibernate不負責
-
increment: 每次插入前,先獲取資料表中最大值,然後+1
-
sequence: 用資料庫提供的sequence機制生成主鍵,需要資料庫支援sequence,mysql不支援
-
hilo: 通過高低位演算法實現
hilo(高低位方式high low)是hibernate中最常用的一種生成方式,需要一張額外的表儲存hi的值。儲存hi值的表至少有一條記錄(只與第一條記錄有關),否則會出現錯誤。可以跨資料庫。
-
native: 使用資料庫原生設定的生成策略
-
UUID:使用uuid演算法生成的id,但是需要注意主鍵必須是String
-
assigned: 由程式設計師自己決定,在儲存時指定id進行儲存
property
除id之外的普通屬性對映
屬性配置引數與id標籤相同
總結
hibernate雖然現在新專案用得不多,但是不可否則它曾經在ORM框架中的地位,同時它也是學習spring data jpa的基礎,hibernate仍是一個優秀的ORM框架