Hibernate框架概述
一、什么是框架
- 軟件的一個半成品,已經幫你完成了部分功能。
- 把一些不確定的東西,按照框架要求,達到相應的功能
Hibernate是JavaEE技術三層架構所用到的技術
二、hibernate簡介
1. hibernate是什么框架
- Hibernate是一個開放源代碼的對象關系映射框架
- 它對JDBC進行了非常輕量級的對象封裝
- 它將POJO與數據庫表建立映射關系,是一個全自動的orm框架
- hibernate可以自動生成SQL語句,自動執行,使得Java程序員可以隨心所欲的使用對象編程思維來操縱數據庫。
- Hibernate可以應用在任何使用JDBC的場合,既可以在Java的客戶端程序使用,也可以在Servlet/JSP的Web應用中使用
- 持久層的ORM框架
2. ORM
- Object Relational Mapping(對象關系映射)。
- 指的是將一個Java中的對象與關系型數據庫中的表建立一種映射關系,從而操作對象就可以操作數據庫中的表。
3. hibernate好處
- 對JDBC訪問數據庫的代碼進行了輕量級封裝,簡化了數據訪問層繁瑣重復性的代碼,減少了內存消耗,加快了運行效率
- 是一個基本JDBC的主流持久化框架,很大程度上簡化了DAO層的編碼工作
- 性能非常好, 映射靈活性比較好,支持多關系數據庫,一對一,一對多,多對多的各種復雜關系
- 可擴展性強,源代碼及API開放,當本身功能不夠用時,可以自行編碼進行擴展
Hibernate基本使用
一、下載框架
二、Hibernate目錄
1. documentation
- Hibernate開發的文檔
2. lib
- Hibernate開發的文檔
- required:Hibernate開發的必須的依賴包
- optional:Hibernate開發的可選的jar包
3. project
- Hibernate提供的參考項目
三、Hibernate使用
1.創建一個項目
- 可以Java項目中使用
- 可以在Web項目中使用都可以
2.引入必須的jar包
- 數據庫的驅動包
- Hibernate開發必須的Jar包
3.建表
CREATE TABLE `customer` (
`cust_id` bigint(32) NOT NULL AUTO_INCREMENT COMMENT '客戶編號(主鍵)',
`cust_name` varchar(32) NOT NULL COMMENT '客戶名稱(公司名稱)',
`cust_source` varchar(32) DEFAULT NULL COMMENT '客戶信息來源',
`cust_industry` varchar(32) DEFAULT NULL COMMENT '客戶所屬行業',
`cust_level` varchar(32) DEFAULT NULL COMMENT '客戶級別',
`cust_phone` varchar(64) DEFAULT NULL COMMENT '固定電話',
`cust_mobile` varchar(16) DEFAULT NULL COMMENT '移動電話',
PRIMARY KEY (`cust_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
4.創建ORM類
可以用lombok插件自動生成set和get方法。
5.創建Hibernate的核心配置文件
- 通常都叫hibernate.cfg.xml
- 創建完畢后, 也有一個約束要引入
- 在org.hibernate包當中可以找到對應的dtd configuration.dtd
- 屬性名記不住
- 在目錄提供的project當中有一個etc
- 在etc當中 有一個hibernate.properties的文件打開
- 打開后,會看到連接各種數據庫時需要的屬性參數
- 需要配置方言
- 不同的數據庫,使用的語言不一樣
- 在hibnate當中,sql語句會自動幫你生成
- 設置方言,就是設置自動生成的語言是哪個數據庫當中的sql
- 配置核心配置文件要加載哪一個映射
- 映射的路徑就是上面創建的跟表相對應的配置文件
- 把全路徑的點,要換成斜杠
- 配置演示
<!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:3307/hibernate</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">abcd</property>
<!-- 配置Hibernate的方言 -->
<property name="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</property>
<!-- 打印SQL -->
<property name="hibernate.show_sql">true</property>
<!-- 格式化SQL -->
<property name="hibernate.format_sql">true</property>
<!-- 自動創建表 -->
<property name="hibernate.hbm2ddl.auto">update</property>
<!--加載映射文件 -->
<mapping resource="com/xzh/hibernate/domain/Customer.hbm.xml" />
</session-factory>
</hibernate-configuration>
6.創建映射關系
-
通過XML的配置文件來進行配置
-
這個配置文件可以任意命名
- 類名.hbm.xml
- 別人一看,就能夠知道是哪個類的映射文件
-
在xml當中引入dtd
- 在hibernate-core.jar包當中
- 在org.hibernate包當中可以找到對應的dtd
- 打開mapping.dtd
- 把里面的約束復制一份,放到xml當中
-
建立類與表的映射
1.建立表與類的映射
2.建立主鍵的映射
3.建立普通屬性的映射 -
配置演示
<?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>
<class name="com.xzh.hibernate.domain.Customer" table="customer">
<!--建立類屬性哪一個是主鍵 還要跟數據庫當中主鍵進行對應 -->
<id name="cust_id" column="cust_id">
<generator class="native" />
</id>
<!--建立類中的普通屬性與數據庫當中字段進行關聯 -->
<property name="cust_name" column="cust_name" />
<property name="cust_source" column="cust_source" />
<property name="cust_industry" column="cust_industry" />
<property name="cust_level" column="cust_level" />
<property name="cust_phone" column="cust_phone" />
<property name="cust_mobile" column="cust_mobile" />
</class>
</hibernate-mapping>
7.創建類執行
@Test
public void test1() {
// 1.加載配置文件
Configuration configure = new Configuration().configure();
// 2.創建sessionFactory --JDBC鏈接池
SessionFactory sessionFactory = configure.buildSessionFactory();
// 3.獲取session --連接對象
Session session = sessionFactory.openSession();
Customer customer = new Customer();
customer.setCust_name("myxq");
customer.setCust_level("2");
// 4.保存
session.save(customer);
// 5.釋放資源
session.close();
sessionFactory.close();
}
常見配置
一、映射配置
1. class標簽
- 作用:建立類與表的映射關系
- 屬性
- name:類的全路徑
- table:表名;類名與表名一致,table可以省略;如果沒有該表,或自動創建一個表。
- catalog:數據庫名,可以不寫
2. ID標簽
- 作用:建立類中的屬性與表中主鍵的對應關系
- 屬性
- name
- column
- length
- type
3. property
- 作用:用於建立類中普通屬性與表的對應關系
- 屬性
- name:類中的屬性名
- column:表中的字段名;如果字段名與類中的屬性名一致,column是可以省略
- length:字段的長度
- 默認數據庫當中已經有長度了
- hibernate是可以根據映射自動建表
- 建表是沒有設定長度,就使用默認的長度
- type:類型;可以不用寫,會自動幫你裝換
- not-null:不允許為空
- unique:唯一的
二、核心配置
1. 必須配置
- 連接數據庫的基本的property參數
- 驅動類
- url路徑
- 用戶名
- 密碼
- 方言
2. 可選配置
-
顯示SQL
hibernate.show_sql -
格式化SQL
hibernate.format_sql -
自動建表
hibernate.hbm2ddl.auto
屬性:- none
不使用hibernate的自動建表 - create
如果數據庫中已經有表,刪除原有表,重新創建,如果沒有表,新建表 - create-drop
如果數據庫中已經有表,刪除原有表,執行操作,刪除這個表。如果沒有表,新建一個,使用完了刪除該表。
最后數據庫中一個表沒有,為了做測試用
把sessionFactory也close掉時才有效果 - update
如果數據庫中有表,使用原有表,如果沒有表,創建新表
更新表結構,如果column沒有時會創建新的一列 - validate
如果沒有表,不會創建表。只會使用數據庫中原有的表
校驗映射和表結構是否一致,不一致就會報錯
- none
3. 引入映射文件
<mapping resource="映射文件全路徑"/>
核心API
一、Configuration
Configuration是Hibernate的配置對象
Configuration 類的作用是對Hibernate 進行配置,以及對它進行啟動。
在Hibernate 的啟動過程中,Configuration 類的實例首先定位映射文檔的位置,讀取這些配置,然后創建一個SessionFactory對象。雖然Configuration 類在整個Hibernate 項目中只扮演着一個很小的角色,但它是啟動hibernate 時所遇到的第一個對象。
通過這個對象去加載它里面的配置,得到里面的數據內容,才能進行后面的工作。
作用
1. 加載核心配置文件
-
核心配置文件是屬性文件
- 名稱為:hibernate.properties
- 直接 configuration cfg = new configuration();
-
核心配置文件是一個xml
- 名稱為:hibernate.cfg.xml
- configuration cfg = new configuration().configure();
2. 加載映射文件
- 屬性文件是沒有辦法加載映射,可以通過config加載映射文件
- configuration.addResource("映射文件的全路徑");
二、SessionFactory
sessionFactory
- SessionFactory接口:SessionFactory接口負責初始化Hibernate。
- 並負責創建Session對象。
- 需要注意的是SessionFactory並不是輕量級的,因為一般情況下,一個項目通常只需要一個SessionFactory就夠,
- 當需要操作多個數據庫時,可以為每個數據庫指定一個SessionFactory。
- 內部維護了Hibernate的連接池和Hibernate的二級緩存
- 一個項目只需要創建一個就行了,因為里面有連接池,連接池創建一個就可以了
配置連接池
C3P0:
引入C3P0的jar包
hibernate-release-5.3.1.Final\lib\optional\c3p0 的目錄下,有三個jar包。
添加C3P0的配置信息
在 hibernate.cfg.xml 中添加C3P0的配置信息。
<!-- C3P0 -->
<property name="connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider</property>
<!--在連接池中可用的數據庫連接的最少數目 -->
<property name="c3p0.min_size">5</property>
<!--在連接池中所有數據庫連接的最大數目 -->
<property name="c3p0.max_size">20</property>
<!--設定數據庫連接的過期時間,以秒為單位, 如果連接池中的某個數據庫連接處於空閑狀態的時間超過了timeout時間,就會從連接池中清除 -->
<property name="c3p0.timeout">120</property>
<!--每3000秒檢查所有連接池中的空閑連接 以秒為單位 -->
<property name="c3p0.idle_test_period">3000</property>
查看日志
- 把 log4j.preperties放到 src下
- 把 log4j-1.2.16.jar放到 lib下
結構
-
輸出源
- console :控制台
- file :文件
-
級別
- error
只顯示error信息 - warn
顯示warn error信息,比自己嚴重的信息 - info
會顯示 info debug trace級別的信息 - debug
調試信息,會把上面的都顯示 - trace
棧信息
- error
工具類
- 一個項目只需要創建一個就行了,因為里面有連接池,連接池創建一個就可以了
- 通過一個工具類來獲取,只需要創建一次
public class HibernateUtil {
public static final SessionFactory sessionFactory;
static {
//1.加載配置文件
Configuration configure = new Configuration().configure();
//2.創建sessionFactory --JDBC 連接池
sessionFactory = configure.buildSessionFactory();
}
public static Session openSession(){
Session session = sessionFactory.openSession();
return session;
}
public static Session getCurrentSession(){
Session session = sessionFactory.getCurrentSession();
return session;
}
}
三、session
- 代表的是hibernate與數據庫的連接對象
- 與數據庫交互的橋梁,通過它來完成與數據庫的增刪改查的工作
session的api
1. 保存方法
save(Object obj)
2. 查詢方法
(1)get(T.class,id)
- 查詢之后,返回的是真實對象本身
- 沒有查詢到指定的id,返回的是一個空值
(2)load(T.class,id)
- 查詢之后返回的是一個代理對象,使用的是第三方的代理機制,javassist.jar
- 沒有查詢到結果直接報一個異常
3. 修改
void update(Object obj)
(1)直接創建對象修改(不建議使用)
- 如果沒有指定其它的字段,會把其它的字段設置為null
Session session = HibernateUtil.openSession();
// 開啟事務
Transaction transaction = session.beginTransaction();
// 更新操作
// 如果沒有指定其它的字段,會把其它的字段設置為null
Customer customer = new Customer();
customer.setCust_id(1L);
customer.setCust_name("myxq_update");
session.update(customer);
// 提交事務
transaction.commit();
// 5.釋放資源
session.close();
(2)查詢之后再修改
- 修改了某一個字段,不會把其它的字段設置為null
Session session = HibernateUtil.openSession();
// 開啟事務
Transaction transaction = session.beginTransaction();
// 更新操作
// 查詢一條記錄后更新
Customer customer = session.get(Customer.class, 1L);
customer.setCust_name("myxq666");
session.update(customer);
// 提交事務
transaction.commit();
// 5.釋放資源
session.close();
4. 刪除
void delete(Object obj)
(1)直接創建對象刪除
- 不支持級聯刪除
Session session = HibernateUtil.openSession();
// 開啟事務
Transaction transaction = session.beginTransaction();
Customer customer = new Customer();
customer.setCust_id(1L);
session.delete(customer);
// 提交事務
transaction.commit();
// 關閉資源
session.close();
(2)查詢之后再刪除
- 支持級聯刪除
Session session = HibernateUtil.openSession();
// 開啟事務
Transaction transaction = session.beginTransaction();
Customer customer = session.get(Customer.class, 2L);
session.delete(customer);
// 提交事務
transaction.commit();
// 關閉資源
session.close();
5. 保存或更新
void saveOrUpdate(Object obj)
- 沒有設置id,是保存的操作
Session session = HibernateUtil.openSession();
Transaction transaction = session.beginTransaction();
// 如果沒有設置id 是保存的操作
Customer customer = new Customer();
customer.setCust_name("6668888---");
customer.setCust_level("3");
session.saveOrUpdate(customer);
transaction.commit();
session.close();
- 設置了id是修改的操作,如果設置的id沒有,就會報錯
Session session = HibernateUtil.openSession();
Transaction transaction = session.beginTransaction();
// 如果沒有設置id 是保存的操作
Customer customer = new Customer();
customer.setCust_id(3L);
customer.setCust_name("6668888---");
customer.setCust_level("3");
session.saveOrUpdate(customer);
transaction.commit();
session.close();
6. 查詢所有
(1)使用HQL的方式
- HQL:Hibernate Query Language 面向對象的查詢語言
Session session = HibernateUtil.openSession();
Transaction transaction = session.beginTransaction();
// 查詢所有 HQL
Query<Customer> query = session.createQuery("from com.xzh.hibernate.domain.Customer");
List<Customer> list = query.list();
for (Customer customer : list) {
System.out.println(customer);
}
transaction.commit();
session.close();
(2)支持SQL語句的方式
- 不建議使用,過時了
Session session = HibernateUtil.openSession();
Transaction transaction = session.beginTransaction();
// 查詢 SQL
NativeQuery sqlQuery = session.createSQLQuery("select * from customer");
List<Object[]> list = sqlQuery.list();
for (Object[] objects : list) {
System.out.println(Arrays.toString(objects));
}
transaction.commit();
session.close();
四、Transaction 事務
- 如果配置了C3P0連接池,必須要寫上事務的代碼,C3P0連接池不會自動幫你提交
- 沒有配置的畫,內部的連接池會自動幫你提交
- Hibernate3當中是不會自動提交的,必須要寫,為了兼容以前的版本,還是寫上事務