Hibernate 框架入門
一、Hibernate框架介紹
什么是Hibernate
我們可以從度娘上摘抄這樣有關Hibernate的介紹:
Hibernate是一個開放源代碼的對象關系映射框架,它對JDBC進行了非常輕量級的對象封裝,它將POJO與數據庫表建立映射關系,是一個全自動的orm框架,hibernate可以自動生成SQL語句,自動執行,使得Java程序員可以隨心所欲的使用對象編程思維來操縱數據庫。Hibernate可以應用在任何使用JDBC的場合,既可以在Java的客戶端程序使用,也可以在Servlet/JSP的Web應用中使用。
從中,我們可以得出這樣的結論:Hibernate是一個輕量級的JDBC封裝,也就是說,我們可以使用Hibernate來完成原來我們使用JDBC完成的操作,也就是與數據庫的交互操作。它是在dao層去使用的。
什么是ORM
對象關系映射(英語:Object Relation Mapping,簡稱ORM,或O/RM,或O/R mapping),是一種程序技術,用于實現面向對象編程語言里不同類型系統的數據之間的轉換。
對象-關系映射,是隨著面向對象的軟件開發方法發展而產生的。面向對象的開發方法是當今企業級應用開發環境中的主流開發方法,關系數據庫是企業級應用環境中永久存放數據的主流數據存儲系統。對象和關系數據是業務實體的兩種表現形式,業務實體在內存中表現為對象,在數據庫中表現為關系數據。內存中的對象之間存在關聯和繼承關系,而在數據庫中,關系數據無法直接表達多對多關聯和繼承關系。因此,對象-關系映射(ORM)系統一般以中間件的形式存在,主要實現程序對象到關系數據庫數據的映射。
ORM模型的簡單性簡化了數據庫查詢過程。使用ORM查詢工具,用戶可以訪問期望數據,而不必理解數據庫的底層結構。
簡單來說,我們使用ORM可以將我們的對象(或類)去進行映射,使得我們可以去操作對象就能完成對表的操作。
為什么使用Hibernate框架
原因如下:
- Hibernate對JDBC訪問數據庫的代碼做了封裝,大大簡化了數據訪問層繁瑣的重復性代碼。
- Hibernate是一個基于JDBC的主流持久化框架,是一個優秀的ORM實現,它很大程度的簡化了dao層編碼工作。
總結:Hibernate是企業級開發中的主流框架,映射的靈活性很出色。它支持很多關系型數據庫。
Hiberate框架學習目標
由于之前學過Hiberate框架,所以這就等于是在復習了。對于Hiberate框架的學習重點,可以總結為:
- 掌握Hiberate的基本配置——即搭建Hiberate開發環境
- 掌握Hiberate常用API——即如何使用Hiberate框架進行開發
- 掌握Hiberate的關聯映射——解決表與表之間存在的關系問題,有1:n(一對多)、 1:1(一對一)、m:n(多對多)關系
- 掌握Hiberate的檢索方式——即掌握Hiberate的查詢
- 掌握Hiberate的優化方式——即提高Hiberate的效率
二、Hibernate的體系結構與開發步驟
Hibernate的體系結構:
Hibernate開發步驟:
- 創建持久化類
- 創建對象-關系映射文件
- 創建Hibernate配置文件
- 通過Hibernate API編寫訪問數據庫的代碼
三、第一個Hibernate程序
介紹完Hibernate框架之后,我們來快速入門Hibernate,對其有一個直觀的了解。
下載Hibernate
可去官網下載Hibernate,我下載的是
所以,之后有關Hibernate的系列文章都是以這個版本為藍圖展開的。下載解壓縮之后,可以看到如下目錄結構:
其中,在lib/required目錄下,包含運行Hibernate項目必須的jar包有:
創建數據庫與表
正如前面所說,Hibernate是一個輕量級的JDBC封裝,也就是說,我們可以使用Hibernate來完成原來我們使用JDBC完成的操作,也就是與數據庫的交互操作。所以我們首先要創建數據庫與表,這里我使用的數據庫是mysql。
create database hibernateTest;
use hibernateTest;
create table t_customer(
id int primary key auto_increment,
name varchar(20),
address varchar(50)
);
創建實體類
首先在Eclipse上創建一個Dynamic Web Project,比如我創建的是hibernate_demo1,然后再切到Java透視圖。這兒我們在cn.itheima.domain包中創建一個實體類——Customer.java。
public class Customer {
private int id;
private String name;
private String address;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "Customer [id=" + id + ", name=" + name + ", address=" + address + "]";
}
}
導入Hibernate框架相關依賴jar包
首先導入lib/required目錄下所有的jar包:
再導入mysql數據庫的驅動jar包:
最后導入日志相關的jar包:
導入完日志相關的jar包之后,我們還須將project/etc/log4j.properties文件導入到工程hibernate_demo1的src目錄下,這樣工程的整個結構就為:
Hibernate的相關配置文件
準備好以上工作之后,我們終于要踏入Hibernate的學習中了。首先我們要編寫Hibernate的相關配置文件,Hibernate的相關配置文件分為兩種:
- xxx.hbm.xml:它主要是用于描述類與數據庫中的表的映射關系。
- hibernate.cfg.xml:它是Hibernate框架的核心配置文件。
有關這兩個配置文件的詳細介紹,我們后面會給大家講解,如果就在這里弄的話,違背了我的初衷了,本文只是在教初學者怎樣快速入門Hibernate。
映射配置文件
首先我們要學會如何編寫映射配置文件,大家要知道編寫完的映射配置文件應與實體類在同一個包下,并且名稱應是類名.hbm.xml,所以我們要在cn.itheima.domain包下創建一個Customer.hbm.xml文件,但是它的約束應該怎么寫呢?可以在Hibernate的核心jar包——hibernate-core-5.0.7.Final.jar的org.hibernate包下查找到hibernate-mapping-3.0.dtd文件,打開該文件,找到如下內容:
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
然后復制黏貼到Customer.hbm.xml文件中。
這里我先給出Customer.hbm.xml文件的內容,但內容不做過多介紹:
<?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 package="cn.itheima.domain">
<!--
name:即實體類的全名
table:映射到數據庫里面的那個表的名稱
catalog:數據庫的名稱
-->
<class name="Customer" table="t_customer" catalog="hibernateTest">
<!-- class下必須要有一個id的子元素 -->
<!-- id是用于描述主鍵的 -->
<id name="id" column="id">
<!-- 主鍵生成策略 -->
<generator class="native"></generator>
</id>
<!--
使用property來描述屬性與字段的對應關系
如果length忽略不寫,且你的表是自動創建這種方案,那么length的默認長度是255
-->
<property name="name" column="name" length="20"></property>
<property name="address" column="address" length="50"></property>
</class>
</hibernate-mapping>
核心配置文件
核心配置文件主要是Hibernate框架所使用的,它主要包含了連接數據庫的相關信息和Hibernate的相關配置等。
現在我們要學會如何編寫Hibernate核心配置文件,大家也要知道編寫完的核心配置文件應在src目錄下,并且名稱應是hibernate.cfg.xml,所以我們要在src目錄下創建一個hibernate.cfg.xml文件,但是它的約束應該怎么寫呢?可以在Hibernate的核心jar包——hibernate-core-5.0.7.Final.jar的org.hibernate包下查找到hibernate-configuration-3.0.dtd文件,打開該文件,找到如下內容:
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
然后復制黏貼到hibernate.cfg.xml文件中。
在這個文件中到底如何配置昵?我們可以參考hibernate-release-5.0.7.Final\project\etc\hibernate.properties文件。這里我先給出hibernate.cfg.xml文件的內容,但內容不做過多介紹:
<?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>
<!-- 配置關于數據庫連接的四個項:driverClass url username password -->
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql:///hibernateTest</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">yezi</property>
<!-- 可以將向數據庫發送的SQL語句顯示出來 -->
<property name="hibernate.show_sql">true</property>
<!-- 格式化SQL語句 -->
<property name="hibernate.format_sql">true</property>
<!-- hibernate的方言 -->
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<!-- 配置hibernate的映射文件所在的位置 -->
<mapping resource="cn/itheima/domain/Customer.hbm.xml" />
</session-factory>
</hibernate-configuration>
Hibernate快速入門開發測試
在cn.itheima.test包下創建一個單元測試類——HibernateTest1.java。
public class HibernateTest1 {
// 保存一個Customer
@Test
public void saveCustomerTest() {
// 創建一個Customer
Customer c = new Customer();
c.setName("葉子");
c.setAddress("武漢");
// 使用Hibernate的API來完成將Customer信息保存到mysql數據庫中的操作
Configuration config = new Configuration().configure(); // Hibernate框架加載hibernate.cfg.xml文件
SessionFactory sessionFactory = config.buildSessionFactory();
Session session = sessionFactory.openSession(); // 相當于得到一個Connection
// 開啟事務
session.beginTransaction();
// 操作
session.save(c);
// 事務提交
session.getTransaction().commit();
session.close();
sessionFactory.close();
}
// 根據id查詢一個Customer對象
@Test
public void findCustomerByIdTest() {
Configuration config = new Configuration().configure(); // Hibernate框架加載hibernate.cfg.xml文件
SessionFactory sessionFactory = config.buildSessionFactory();
Session session = sessionFactory.openSession(); // 相當于得到一個Connection
// 開啟事務
session.beginTransaction();
// 根據業務來編寫代碼
// Customer c = session.get(Customer.class, 1);
Customer c = session.load(Customer.class, 1);
System.out.println(c.getName());
// 事務提交
session.getTransaction().commit();
session.close();
sessionFactory.close();
}
// 修改操作
@Test
public void updateCustomerTest() {
Configuration config = new Configuration().configure(); // Hibernate框架加載hibernate.cfg.xml文件
SessionFactory sessionFactory = config.buildSessionFactory();
Session session = sessionFactory.openSession(); // 相當于得到一個Connection
// 開啟事務
session.beginTransaction();
// 根據業務來編寫代碼
Customer c = session.get(Customer.class, 1);
c.setName("鄭敏");
session.update(c); // 修改操作
// 事務提交
session.getTransaction().commit();
session.close();
sessionFactory.close();
}
// 刪除操作---根據id進行刪除
@Test
public void deleteCustomerTest() {
Configuration config = new Configuration().configure(); // Hibernate框架加載hibernate.cfg.xml文件
SessionFactory sessionFactory = config.buildSessionFactory();
Session session = sessionFactory.openSession(); // 相當于得到一個Connection
// 開啟事務
session.beginTransaction();
// 根據業務來編寫代碼
Customer c = session.get(Customer.class, 1);
session.delete(c); // 刪除操作
// 事務提交
session.getTransaction().commit();
session.close();
sessionFactory.close();
}
// 查詢所有Customer
@Test
public void findAllCustomerTest() {
Configuration config = new Configuration().configure(); // Hibernate框架加載hibernate.cfg.xml文件
SessionFactory sessionFactory = config.buildSessionFactory();
Session session = sessionFactory.openSession(); // 相當于得到一個Connection
// 開啟事務
session.beginTransaction();
// 根據業務來編寫代碼
Query query = session.createQuery("from Customer"); // HQL語句,它類似于SQL語句
List<Customer> list = query.list();
System.out.println(list);
// 事務提交
session.getTransaction().commit();
session.close();
sessionFactory.close();
}
}
測試如若都無任何問題,則我們就算入門Hibernate了。
Hibernate執行原理總結
可從度娘上摘抄到如下文字:
- 通過Configuration().configure();讀取并解析hibernate.cfg.xml配置文件。
- 由hibernate.cfg.xml中的讀取解析映射信息。
- 通過config.buildSessionFactory();得到sessionFactory。
- sessionFactory.openSession();得到session。
- session.beginTransaction();開啟事務。
- persistent operate; 執行你自己的操作。
- session.getTransaction().commit();提交事務。
- 關閉session。
- 關閉sessionFactory。
四、第二個Hibernate程序——完整的數據庫操作(CRUD)
前面我們寫了一個Hibernate入門的小程序。現在我們來寫第二個Hibernate程序——實現對數據庫完整的操作(CRUD)。
我們首先創建一個工具類——HibernateUtils.java,該工具類的作用專門用來獲取全局唯一的SessionFactory,以及從全局唯一的SessionFactory中打開一個Session。
public class HibernateUtils {
// SessionFactory全局只需要有一個就可以了,因為它的創建和銷毀需要消耗大量的資源,初始化信息會比較多,并且它是線程安全的,可以在多線程的環境下使用它
private static SessionFactory sessionFactory;
static {
// 初始化SessionFactory方式一:
/*
Configuration cfg = new Configuration(); // 代表配置文件的一個對象
cfg.configure(); // 讀取默認的配置文件(hibernate.cfg.xml)
// cfg.configure("hibernate.cfg.xml"); // 讀取指定位置的配置文件
sessionFactory = cfg.buildSessionFactory();
*/
// 初始化SessionFactory方式二:
sessionFactory = new Configuration() //
.configure() //
.buildSessionFactory(); // 方法鏈
}
/**
* 獲取全局唯一的SessionFactory
*
* @return
*/
public static SessionFactory getSessionFactory() {
return sessionFactory;
}
/**
* 從全局唯一的SessionFactory中打開一個Session
*
* @return
*/
public static Session openSession() {
return sessionFactory.openSession();
}
}
思考一個問題,若我們要編寫代碼實現對數據庫完整的操作,那么就必定涉及到分頁查詢,要實現分頁查詢,我們一定要弄清楚分頁設計結構圖。所以我們還要創建一個類——QueryResult.java,用于封裝查詢結果。
public class QueryResult {
private int count; // 總記錄數
private List list; // 一頁的數據
public QueryResult(int count, List list) {
this.count = count;
this.list = list;
}
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
public List getList() {
return list;
}
public void setList(List list) {
this.list = list;
}
}
最后,我們創建一個類——UserDao.java。UserDao類里面編寫代碼實現對數據庫完整的操作(CRUD)。
public class UserDao {
/*
* 保存
*/
public void save(User user) {
Session session = HibernateUtils.openSession();
try {
Transaction tx = session.beginTransaction(); // 開啟事務
session.save(user);
tx.commit(); // 提交事務
} catch (RuntimeException e) {
session.getTransaction().rollback(); // 回滾事務
throw e;
} finally {
session.close(); // 關閉session
}
}
/*
* 更新
*/
public void update(User user) {
Session session = HibernateUtils.openSession();
Transaction tx = null;
try {
tx = session.beginTransaction();
session.update(user);// 操作
tx.commit();
} catch (RuntimeException e) {
tx.rollback();
throw e;
} finally {
session.close();
}
}
/*
* 刪除
*/
public void delete(int id) {
Session session = HibernateUtils.openSession();
Transaction tx = null;
try {
tx = session.beginTransaction();
Object user = session.get(User.class, id); // 要先獲取到這個對象
session.delete(user); // 刪除的是實體對象
tx.commit();
} catch (RuntimeException e) {
tx.rollback();
throw e;
} finally {
session.close();
}
}
/*
* 根據id查詢一個User數據
*/
public User getById(int id) {
Session session = HibernateUtils.openSession();
Transaction tx = null;
try {
tx = session.beginTransaction();
User user = (User) session.get(User.class, id);// 操作
tx.commit();
return user;
} catch (RuntimeException e) {
tx.rollback();
throw e;
} finally {
session.close();
}
}
/*
* 查詢所有
*/
public List<User> findAll() {
Session session = HibernateUtils.openSession();
Transaction tx = null;
try {
tx = session.beginTransaction();
// 方式一:使用HQL語句
List<User> list = session.createQuery("FROM User").list(); // 使用HQL查詢
tx.commit();
return list;
} catch (RuntimeException e) {
tx.rollback();
throw e;
} finally {
session.close();
}
}
/**
* 分頁的查詢數據列表
* @param firstResult 從結果列表中的哪個索引開始取數據
* @param maxResults 最多取多少條數據
* @return 一頁的數據列表
*/
@SuppressWarnings("unchecked")
public QueryResult findAll(int firstResult, int maxResults) {
Session session = HibernateUtils.openSession();
Transaction tx = null;
try {
tx = session.beginTransaction();
// 查詢一頁的數據列表
// 方式一:
// Query query = session.createQuery("FROM User");
// query.setFirstResult(firstResult);
// query.setMaxResults(maxResults);
// List<User> list = query.list(); // 使用HQL查詢
// 方式二:方法鏈
List<User> list = session.createQuery( //
"FROM User") //
.setFirstResult(firstResult) //
.setMaxResults(maxResults) //
.list();
// 查詢總記錄數
// session.createQuery("SELECT COUNT(*) FROM User").list().get(0);
// Long count = (Long) session.createQuery("SELECT COUNT(*) FROM User").uniqueResult();
Long count = (Long) session.createQuery( //
"SELECT COUNT(*) FROM User") //
.uniqueResult();
tx.commit();
// 返回結果
return new QueryResult(count.intValue(), list);
} catch (RuntimeException e) {
tx.rollback();
throw e;
} finally {
session.close();
}
}
}
在如下兩個方法中:
public List<User> findAll()
- public QueryResult findAll(int firstResult, int maxResults)
我們使用到了Hibernate查詢語句——HQL(Hibernate Query Language),后面將會詳細講解,這里稍微了解一下即可,我們只要會用就好。
HQL(Hibernate Query Language)與SQL相似,查詢的是對象和對象中的屬性,關鍵字不區分大小寫,但類名與屬性名區分大小寫;而SQL查詢的是表和表中的字段,同樣也不區分大小寫。
接下來,為方便測試,我們使用單元測試來測試以上編寫的代碼。我們只要右鍵點擊UserDao類→New→JUnit Test Case,如下:
接下來會彈出如下對話框:
這是要幫我們自動創建UserDao測試類的節奏。
接著點擊Next按鈕,在彈出的對話框中選中我們要測試的UserDao類中的方法。
最后點擊Finish完成,這時Eclipse就幫我們自動創建UserDao類的測試類
——UserDaoTest.java了,然后我們再在其中編寫測試代碼。
public class UserDaoTest {
private UserDao userDao = new UserDao();
@Test
public void testSave_1() {
User user = new User();
user.setName("張三");
// 保存
userDao.save(user);
}
@Test
public void testGetById() {
User user = userDao.getById(1);
System.out.println(user);
}
@Test
public void testUpdate() {
// 從數據庫中獲取一條存在的數據
User user = userDao.getById(1);
user.setName("李四");
// 更新
userDao.update(user);
}
@Test
public void testDelete() {
userDao.delete(1);
}
// -------------------------
@Test
public void testSave_25() {
for (int i = 1; i <= 25; i++) {
User user = new User();
user.setName("test_" + i);
userDao.save(user); // 保存
}
}
@Test
public void testFindAll() {
List<User> list = userDao.findAll();
for (User user : list) {
System.out.println(user);
}
}
@Test
public void testFindAllIntInt() {
// 查詢
// QueryResult qr = userDao.findAll(0, 10); // 第1頁,每頁10條
// QueryResult qr = userDao.findAll(10, 10); // 第2頁,每頁10條
QueryResult qr = userDao.findAll(20, 10); // 第3頁,每頁10條
// 顯示結果
System.out.println("總記錄數:" + qr.getCount());
for (User user : (List<User>) qr.getList()) {
System.out.println(user);
}
}
}
測試通過,Hibernate入門完結!
智能推薦
Hibernate框架學習筆記_Hibernate入門
數據持久化的介紹 ORM的概念及實現 了解Hibernate的作用 Hibernate的體系結構 創建第一個Hibernate的應用 一、持久化介紹 面向對象的開發方法已經成為開發方法中的主流。對象只能保存在內存中,一旦發生斷電或其他突然性狀況致使計算機不能正常工作時,內存中的數據將會全部丟失。為達到數據永久保存的目的,就必須對數據進行持久化操作。 數據的持久化操作,一般情況下都是將數據&ldqu...
freemarker + ItextRender 根據模板生成PDF文件
1. 制作模板 2. 獲取模板,并將所獲取的數據加載生成html文件 2. 生成PDF文件 其中由兩個地方需要注意,都是關于獲取文件路徑的問題,由于項目部署的時候是打包成jar包形式,所以在開發過程中時直接安照傳統的獲取方法沒有一點文件,但是當打包后部署,總是出錯。于是參考網上文章,先將文件讀出來到項目的臨時目錄下,然后再按正常方式加載該臨時文件; 還有一個問題至今沒有解決,就是關于生成PDF文件...
電腦空間不夠了?教你一個小秒招快速清理 Docker 占用的磁盤空間!
Docker 很占用空間,每當我們運行容器、拉取鏡像、部署應用、構建自己的鏡像時,我們的磁盤空間會被大量占用。 如果你也被這個問題所困擾,咱們就一起看一下 Docker 是如何使用磁盤空間的,以及如何回收。 docker 占用的空間可以通過下面的命令查看: TYPE 列出了docker 使用磁盤的 4 種類型: Images:所有鏡像占用的空間,包括拉取下來的鏡像,和本地構建的。 Con...
requests實現全自動PPT模板
http://www.1ppt.com/moban/ 可以免費的下載PPT模板,當然如果要人工一個個下,還是挺麻煩的,我們可以利用requests輕松下載 訪問這個主頁,我們可以看到下面的樣式 點每一個PPT模板的圖片,我們可以進入到詳細的信息頁面,翻到下面,我們可以看到對應的下載地址 點擊這個下載的按鈕,我們便可以下載對應的PPT壓縮包 那我們就開始做吧 首先,查看網頁的源代碼,我們可以看到每一...
猜你喜歡
Linux C系統編程-線程互斥鎖(四)
互斥鎖 互斥鎖也是屬于線程之間處理同步互斥方式,有上鎖/解鎖兩種狀態。 互斥鎖函數接口 1)初始化互斥鎖 pthread_mutex_init() man 3 pthread_mutex_init (找不到的情況下首先 sudo apt-get install glibc-doc sudo apt-get install manpages-posix-dev) 動態初始化 int pthread_...
統計學習方法 - 樸素貝葉斯
引入問題:一機器在良好狀態生產合格產品幾率是 90%,在故障狀態生產合格產品幾率是 30%,機器良好的概率是 75%。若一日第一件產品是合格品,那么此日機器良好的概率是多少。 貝葉斯模型 生成模型與判別模型 判別模型,即要判斷這個東西到底是哪一類,也就是要求y,那就用給定的x去預測。 生成模型,是要生成一個模型,那就是誰根據什么生成了模型,誰就是類別y,根據的內容就是x 以上述例子,判斷一個生產出...
styled-components —— React 中的 CSS 最佳實踐
https://zhuanlan.zhihu.com/p/29344146 Styled-components 是目前 React 樣式方案中最受關注的一種,它既具備了 css-in-js 的模塊化與參數化優點,又完全使用CSS的書寫習慣,不會引起額外的學習成本。本文是 styled-components 作者之一 Max Stoiber 所寫,首先總結了前端組件化樣式中的最佳實踐原則,然后在此基...