Hibernate是什麼?
- Hibernate是一個框架(framework);
- Hibernate是一個ORM框架(Object Relation Mapping,對象關係映射);
- Hibernate處於項目的持久層(故也稱之爲持久層框架);(持久的意思就是把對象的信息保存到數據庫或者是文件中)
- Hibernate實際上就是對JDBC進行了輕量級封裝;
- Hibernate的基礎還是Java的反射機制。
總結:Hibernate是對JDBC進行輕量級封裝的ORM框架,充當項目的持久層。
Hibernate的好處
- 引入Hibernate可以使工作人員角色細化,讓程序員更關心業務流程。讓數據庫人員關注數據庫相關的各種操作;
- 分層更清晰,耦合性更小;
- 通用性強:可以更輕鬆的從一個數據庫平臺轉移到別的平臺;
- 對象化:把關係型數據庫變成了Java的對象,更加方便操作;
- 性能保證:Hibernate可能按不同的數據庫,處理不同的操作時用最優化的SQL語句,不用我們去想;
- 增加了程序的魯棒性。
快速入門案例
Hibernate可以用在J2SE項目中,也可以用在J2EE項目中。(Struts是Web層框架,只能用在J2EE項目中)
開發流程:
1. 創建一個項目
2. 引入Hibernate的開發包
3. 開發Hibernate有三種方式:
(1)由Domain Object -> mapping -> db (官方推薦)
(2)由DB開始,用工具生成mapping和Domain Object (使用較多)
(3)由映射文件開始
4. 我們使用第二種方式開發,使用MySQL數據庫,先創建employee表
CREATE TABLE employee (
id INT NOT NULL AUTO_INCREMENT,
PRIMARY KEY(id),
NAME VARCHAR (64) NOT NULL,
email VARCHAR (64) NOT NULL,
hiredate date NOT NULL
);
5. 開發domain對象和對象關係映射文件
對象關係文件:用於指定domain對象和表的映射關係,該文件的取名有要遵循一定的規範:domain對象.hbm.xml,一般放在和domian對象同一個文件夾下(即同一個包下)
domain對象的要求如下:
- (1) domain對象應該和一張表對應
- (2) 一般我們放在com.xxx.domain包下
- (3) domain需要一個主鍵屬性(用於標識一個domain對象)
- (4) 除了主鍵屬性外,它應當還有其他屬性,屬性的訪問權限爲private
- (5) 提供setter和getter方法
- (6) 應當有一個無參的構造方法(hibernate反射)
domain對象如下:
public class Employee {
private Integer id;
private String name;
private String email;
private Date hiredate;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Date getHiredate() {
return hiredate;
}
public void setHiredate(Date hiredate) {
this.hiredate = hiredate;
}
}
配置文件如下:
<?xml version="1.0" encoding="utf-8" ?>
<!--XML文件需要DTD文件來規定格式-->
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/xsd/hibernate-mapping-3.0.dtd">
<!--package用於指定映射domain對象所在的包-->
<hibernate-mapping package="com.gavin.domain">
<!--name用於指定映射的domain對象,table用於指定數據庫中的表-->
<class name="Employee" table="employee">
<!--id元素用於指定domain對象中與表對應的主鍵屬性,column用於指定表中的主鍵屬性-->
<!--當然一般我們的命名是一致的,這裏都是id-->
<id name="id" column="id" type="java.lang.Integer"/>
<!--對其他屬性還要配置-->
<!--指定屬性name,是String類型的,其對應表中的列爲name,並且不允許爲空-->
<property name="name" type="java.lang.String">
<column name="name" not-null="false"/>
</property>
<property name="email" type="java.lang.String">
<column name="email" not-null="false"/>
</property>
<property name="hiredate" type="java.util.Date">
<column name="hiredate" not-null="false"/>
</property>
</class>
</hibernate-mapping>
6. 手動配置我們的hibernate.cfg.xml文件,該文件用於配置連接數據庫的類型,driver,用戶名,密碼,url等等,同時還要管理對象關係映射文件。該文件的名稱我們一般不修改。
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>
<!--hibernate設計者給我們提供了一些常用設置的配置-->
<!--show_sql可以讓Hibernate輸出SQL語句-->
<property name="show_sql">true</property>
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.url">jdbc:mysql://localhost:3333/hibernate</property>
<property name="connection.username">root</property>
<property name="connection.password">your_password</property>
<!--配置dialect方言,明確告訴Hibernate現在連接的是哪種數據庫-->
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<!-- 下面這個配置指定Hibernate自動幫我們創建表(如果數據庫中沒有該表的話)。-->
<!--create表示每次使用都創建新表,如果存在表,則刪除過再創建-->
<!--update則表示如果表結構有變化,則刪除後創建新表,如果沒有,則不創建新表-->
<!-- <property name="hbm2ddl.auto">create</property> -->
<!--mapping用於指定對象關係映射文件-->
<mapping resource="com/gavin/domain/Employee.hbm.xml"/>
</session-factory>
</hibernate-configuration>
7. 測試文件TestMain.java
package com.gavin.view;
import com.gavin.domain.Employee;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import java.util.Date;
public class TestMain {
public static void main(String[] args) {
addEmployee();
}
/**
* 向數據庫中添加一個Employee對象
*/
public static void addEmployee() {
// 我們使用Hibernate完成CRUD操作
// 這裏我們只見對象,不見表了;也就是說,我們不關心表了,對錶的操作由Hibernate接管了
// 我們不使用service,直接測試
// 1.創建Configuration,並調用configure方法讀取配置文件完成初始化,
// 默認的文件名爲hibernate.cfg.xml,故可以不寫文件名
Configuration configuration = new Configuration().configure("hibernate.cfg.xml");
// 2.創建SessionFactory,這是一個會話工廠,是一個重量級的類
SessionFactory sessionFactory = configuration.buildSessionFactory();
// 3.創建一個會話,相當於JDBC中的Connection
Session session = sessionFactory.openSession();
/*對於Hibernate而言,要求程序在進行增加,刪除,修改的時候使用事務提交*/
Transaction transaction = session.beginTransaction();
// 4.添加一個Employee
Employee employee = new Employee();
employee.setName("Gavin");
employee.setEmail("[email protected]");
employee.setHiredate(new Date());
// 之前的插入是insert語句,現在不用了
// 直接調用session.save(),就可以將Employee對象插入數據庫
session.save(employee); // save employee 就是持久化該對象(把數據保存到了數據庫中)
transaction.commit();
session.close();
}
}
運行上述測試文件,Hibernate會向數據庫中插入一條數據。由於我們配置Hibernate的時候,設置了show_sql
屬性爲true
,所以控制檯會輸出被Hibernate執行的SQL語句。
下圖展示了在運行測試代碼前後查詢數據庫的結果。
我們的目錄結構如下:
更多的測試
1. SessionFactory是一個重量級的類,所以應該保證其是單態的。所以將其封裝起來。如下:
package com.gavin.util;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
/**
* 單例模式
*
* 在使用Hibernate開發項目的時候,一定保證只有一個SessionFactory,
* 原則:理論上是一個數據庫對應一個SessionFactory,項目中用了兩個數據庫,則可以存在兩個SessionFactory
*/
final public class MySessionFactory {
private static SessionFactory sessionFactory;
static{
sessionFactory = new Configuration().configure().buildSessionFactory();
}
public static SessionFactory getSessionFactory() {
return sessionFactory;
}
private MySessionFactory(){}
}
2. 此時我們再測試對Employee的修改,編寫updateEmployee
方法並調用執行。
public static void main(String[] args) {
// addEmployee();
updateEmployee();
}
/**
* 修改Employee
*/
public static void updateEmployee() {
// 獲取一個會話
Session session = MySessionFactory.getSessionFactory().openSession();
// 獲取要修改的對象,再修改
Transaction transaction = session.beginTransaction();
// load是通過主鍵屬性獲取對象實例 <--> 與表的記錄對應
Employee employee = session.load(Employee.class, 1);
// 下面這句話會導致一個update語句產生
employee.setEmail("[email protected]");
transaction.commit();
session.close();
}
執行成功之後,數據庫中的數據如下:
可以看到,數據庫中的數據已經被修改了。
3. 同樣的我們可以測試刪除。
public static void main(String[] args) {
// addEmployee();
// updateEmployee();
delectEmployee();
}
public static void delectEmployee() {
// 獲取一個會話
Session session = MySessionFactory.getSessionFactory().openSession();
// 刪除,先獲取該僱員,然後再刪除
Transaction transaction = session.beginTransaction();
Employee employee = session.load(Employee.class, 1);
session.delete(employee);
transaction.commit();
session.close();
}
4. 查詢的功能之後再作介紹。我們已經使用了session.load()
方法來獲取一個對象,但是查詢是多樣化的,並不一定非要通過id
號來查詢,而且有更多的查詢需求比如分頁等等,後面會重點介紹HQL
語句。
使用工具(IDEA)自動生成domain對象和hbm配置文件
前面提到,開發Hibernate有三種方式,前面的示例我們使用了第二種開發方式,即:由DB開始,用工具生成mapping和Domain Object (使用較多)
。
在前面的示例中,我們都是通過手動地編寫代碼和配置文件,其實這些步驟完全可以由工具幫我們完成。
MyEclipse中有這樣的操作,同樣IDEA也是有的。下面介紹一下在IDEA裏面的操作。
1. 首先目錄結構是下面這樣的,我們將原來的domain對象和配置文件先備份在pojo
包中。同時刪除hibernate.cfg.xml
文件中的mapping
配置(這個配置待會兒工具也會自動幫我們加上)。
在Project框下面有Persistence工具框,這就是我們操作Hibernate工具的地方。
2. 首先我們要配置一下數據庫
在跳出來的對話框中設置數據庫連接的參數,IP,用戶名和密碼等。
3. 右鍵HibernateTest
,依次選擇Generate Persistence Mapping
和 By Database Scheme
4. 在跳出來的對話框中進行設置,如下:
5. 上述操作完成之後,我們可以在domain包下看到生成的Employee
對象和Employee.hbm.xml
關係映射文件。
這時我們再次測試TestMain
,發現沒有任何異常。