1. hibernate框架java
框架的含義:mysql
javaEE三層開發框架及hibernate框架對應的位置以下:程序員
Hibernate框架優勢: 操做數據庫的時候,能夠以面向對象的方式來完成.不須要書寫SQL語句web
Hibernate框架:是當今主流的Java持久層框架之一,因爲它具備簡單易學、靈活性強、擴展性強等特色,可以大大地簡化程序的代碼量,提升工做效率,所以受到廣大開發人員的喜好。sql
Hibernate是一個開放源代碼的ORM(object relationship mapping,關係對象映射)框架,它對JDBC進行了輕量級的對象封裝,使得Java開發人員可使用面向對象的編程思想來操做數據庫。數據庫
Hibernate是一個開放源代碼的對象關係映射框架,它對JDBC進行了很是輕量級的對象封裝,它將POJO與數據庫表創建映射關係,是一個全自動的orm框架,hibernate能夠自動生成SQL語句,自動執行,使得Java程序員能夠爲所欲爲的使用對象編程思惟來操縱數據庫。 Hibernate能夠應用在任何使用JDBC的場合,既能夠在Java的客戶端程序使用,也能夠在Servlet/JSP的Web應用中使用,最具革命意義的是,Hibernate能夠在應用EJB的J2EE架構中取代CMP,完成數據持久化的重任。編程
爲何學習Hibernate?緩存
使用傳統的JDBC開發應用系統時,若是是小型應用系統,並不以爲有什麼麻煩,可是因爲大型應用系統的開發,使用JDBC就會顯得力不從心。例如對幾10、幾百張包含幾十個字段的表進行插入操做時,編寫的SQL語句不但很長,並且繁瑣,容易出錯;在讀取數據時,須要寫多條getXxx語句從結果集中取出各個字段的信息,不但枯燥重複,而且工做量很是大。爲了提升數據訪問層的編程效率,Gravin King開發出了一個當今最流行的ORM框架,它就是Hibernate框架。安全
所謂的ORM就是利用描述對象和數據庫表之間映射的元數據,自動把Java應用程序中的對象,持久化到關係型數據庫的表中(自動建立表)。經過操做Java對象,就能夠完成對數據庫表的操做。能夠把ORM理解爲關係型數據和對象的一個紐帶,開發人員只須要關注紐帶一端映射的對象便可。ORM原理:session
與其它操做數據庫的技術相比,Hibernate具備如下優點:
orm分4級
hibernate屬於4級:徹底面向對象操做數據庫
mybatis屬於2級
dbutils屬於1級
Hibernate5.0.7的目錄介紹:
2. Hibernate入門
框架搭建
lib/required子目錄中,包含的JAR包
驅動包
日誌記錄包
持久化類是應用程序中的業務實體類,這裏的持久化是指類的對象可以被持久化保存到數據庫中。
Hibernate使用普通Java對象(Plain Old Java Object),即POJO的編程模式來進行持久化。POJO類中包含的是與數據庫表相對應的各個屬性,這些屬性經過getter和setter方法來訪問,對外部隱藏了內部的實現細節。下面就來編寫Customer持久化類。
在項目src目錄下,建立cn.eagle.domain包,並在保重建立類Customer(對應數據庫表cst_customer),Customer類包含了與cst_customer數據表字段對應的屬性,以及相應的getXxx()和setXxx()方法。
1 package cn.eagle.domain; 2 3 public class Customer { 4 5 private Long cust_id; 6 private String cust_name; 7 private String cust_source; 8 private String cust_industry; 9 private String cust_level; 10 private String cust_phone; 11 private String cust_mobile; 12 13 public Long getCust_id() { 14 return cust_id; 15 } 16 17 public void setCust_id(Long cust_id) { 18 this.cust_id = cust_id; 19 } 20 21 public String getCust_name() { 22 return cust_name; 23 } 24 25 public void setCust_name(String cust_name) { 26 this.cust_name = cust_name; 27 } 28 29 public String getCust_source() { 30 return cust_source; 31 } 32 33 public void setCust_source(String cust_source) { 34 this.cust_source = cust_source; 35 } 36 37 public String getCust_industry() { 38 return cust_industry; 39 } 40 41 public void setCust_industry(String cust_industry) { 42 this.cust_industry = cust_industry; 43 } 44 45 public String getCust_level() { 46 return cust_level; 47 } 48 49 public void setCust_level(String cust_level) { 50 this.cust_level = cust_level; 51 } 52 53 public String getCust_phone() { 54 return cust_phone; 55 } 56 57 public void setCust_phone(String cust_phone) { 58 this.cust_phone = cust_phone; 59 } 60 61 public String getCust_mobile() { 62 return cust_mobile; 63 } 64 65 public void setCust_mobile(String cust_mobile) { 66 this.cust_mobile = cust_mobile; 67 } 68 69 @Override 70 public String toString() { 71 return "Customer [cust_id=" + cust_id + ", cust_name=" + cust_name + ", cust_source=" + cust_source 72 + ", cust_industry=" + cust_industry + ", cust_level=" + cust_level + ", cust_phone=" + cust_phone 73 + ", cust_mobile=" + cust_mobile + "]"; 74 } 75 76 }
實體類Customer目前還不具有持久化操做的能力,而Hibernate須要知道實體類Customer映射到數據庫Hibernate中的哪一個表,以及類中的哪一個屬性對應數據庫表中的哪一個字段,這些都須要在映射文件中配置。
在實體類Customer所在的包中,建立一個名稱爲Customer.hbm.xml的映射文件,在該文件中定義了實體類Customer的屬性是如何映射到cst_customer表的列上的。
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> 3 <hibernate-mapping> 4 <class name="cn.eagle.domain.Customer" table="cst_customer"> 5 <id name="cust_id" column="cust_id"> 6 <generator class="native"></generator> 7 </id> 8 <property name="cust_name" column="cust_name"></property> 9 <property name="cust_source" column="cust_source"></property> 10 <property name="cust_industry" column="cust_industry"></property> 11 <property name="cust_level" column="cust_level"></property> 12 <property name="cust_phone" column="cust_phone"></property> 13 <property name="cust_mobile" column="cust_mobile"></property> 14 </class> 15 </hibernate-mapping>
Hibernate的映射文件反映了持久化類和數據庫表的映射信息,而Hibernate的配置文件則主要用來配置數據庫鏈接以及Hibernate運行時所須要的各個屬性的值。在項目的src下建立一個名稱爲hibernate.cfg.xml的文件
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd" > 3 <hibernate-configuration> 4 <session-factory> 5 <property name="hibernate.connection.dirver_class">com.mysql.jdbc.Driver</property> 6 <property name="hibernate.connection.url">jdbc:mysql:///day24_db</property> 7 <property name="hibernate.connection.username">root</property> 8 <property name="hibernate.connection.password">toor</property> 9 <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property> 10 <property name="hibernate.show_sql">true</property> 11 <property name="hibernate.format_sql">true</property> 12 <property name="hibernate.hbm2ddl.auto">update</property> 13 <mapping resource="cn/eagle/domain/Customer.hbm.xml"/> 14 </session-factory> 15 </hibernate-configuration>
3. Hibernate配置文件詳解
在以上部分中,咱們已經接觸過Hibernate的映射文件和配置文件。接下來,將對這些文件進行詳細的講解。
<?xml version="1.0" encoding="UTF-8"?>
<!-- 映射文件的dtd信息 -->
<!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:完整類名;
table:數據庫表名。(若是類名和表名是一致的,那麼table屬性能夠省略) -->
<class name="cn.eagle.domain.Customer" table="cst_customer">
<!-- id元素:配置主鍵映射的屬性
name:主鍵對應的屬性名;
column(可選):填寫表中的主鍵列名。默認值:列名會默認使用屬性名;
type(可選):填寫列(屬性)的類型。Hibernate會自動檢測實體的屬性類型。
每一個類型有三種填法:java類型|hibernate類型(默認)|數據庫類型;
not-null(可選):配置該屬性(列)是否不能爲空。默認值:false
length(可選):配置數據庫中列的長度,默認值:使用數據庫類型的最大長度
-->
<id name="cust_id" column="cust_id">
<generator class="native"></generator> // 主鍵的生成策略
</id>
<!-- 其它屬性使用property標籤來映射 -->
<property name="cust_name" column="cust_name"></property>
<property name="cust_source" column="cust_source"></property>
<property name="cust_industry" column="cust_industry"></property>
<property name="cust_level" column="cust_level"></property>
<property name="cust_phone" column="cust_phone"></property>
<property name="cust_mobile" column="cust_mobile"></property>
</class>
</hibernate-mapping>
映射文件一般是一個xml文件便可,但通常命名爲類名.hbm.xml
上述兩種配置文件是等價的,具體使用哪一個能夠自由選擇。XML格式的配置文件更易於修改,配置能力更強,當改變低層應用配置時不須要改變和從新編譯代碼,只修改配置文件的相應屬性便可,而properties格式的文件則不具備次優點,所以,在實際開發項目中,大多數狀況會使用XML格式的配置文件。下面將對XML格式的配置文件進行詳細介紹。
hibernate.cfg.xml配置文件通常在開發時會放置在src的源文件夾下,發佈後,該文件會在項目的WEB-INF/classes路徑下。配置文件的經常使用配置信息以下所示。
<?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>
<!-- 5個必選鏈接數據庫基本參數屬性
hibernate.connection.dirver_class 數據庫驅動
hibernate.connection.url 數據庫url
hibernate.connection.username 數據庫鏈接用戶名
hibernate.connection.password 數據庫鏈接密碼
hibernate.dialect 數據庫方言,不一樣的數據庫中,sql語法略有區別,
指定方言可讓hibernate框架在生成sql語句時,針對數據庫的方言生成;
sql99標準:DDL 定義語言 庫表的增刪改查
DCL 控制語言 事務、權限
DML 操縱語言 增刪改查
注意: Mysql在選擇方言時,請選擇最短的方言
hibernate.connection.autocommit 可選,事務是否自動提交
-->
<property name="hibernate.connection.dirver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql:///day24_db</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">toor</property>
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<!-- 3個可選屬性
hibernate.show_sql 將hibernate生成的sql語句打印到控制檯
hibernate.format_sql 將hibernate生成的sql語句格式化(語法縮進)
hibernate.hbm2ddl.auto (auto scheme export 自動導出表結構,自動建表)
create: 自動建表.每次框架運行都會建立新的表,之前的表將會被覆蓋,表數據會丟失。(開發環境中測試使用)
create-drop: 自動建表。每次框架運行結束都會將全部表刪除。(開發環境中測試使用)
update: 推薦使用 自動生成表,若是已經存在不會再生成,若是表有變更,自動更新表(不會刪除任何數據)
validate: 校驗 不自動生成表。每次啓動會校驗數據庫中表是否正確,只會使用原有的表 -->
<property name="hibernate.show_sql">true</property>
<property name="hibernate.format_sql">true</property>
<property name="hibernate.hbm2ddl.auto">update</property>
<!-- 引入orm源數據
路徑書寫:填寫src下的路徑 -->
<mapping resource="cn/eagle/domain/Customer.hbm.xml" />
</session-factory>
</hibernate-configuration>
4. Hibernate API詳解
Configuration主要用於Hibernate框架加載映射文件,它的做用是對Hibernate進行配置,以及對它進行啓動。在Hibernate的啓動過程當中,Configuration類的實例首先定位映射文檔的位置,讀取這些配置,而後建立一個SessionFactory對象。雖然Configuration類在整個Hibernate項目中只扮演着一個很小的角色,但他是啓動hibernate時所遇到的第一個對象;
Configuration實例用於啓動、加載、管理hibernate的配置文件信息。在啓動Hibernate的過程當中,Configuration實例首先肯定Hibernate配置文件的位置,而後讀取相關配置,最後建立一個惟一的SessionFactory實例。Configuration對象只存在於系統的初始化階段,它將SessionFactory建立完成後,就完成了本身的使命。
Configuration cfg = new Configuration().configure();
此種方式默認會去src下讀取hibernate.cfg.xml配置文件。若是不想使用默認的hibernate.cfg.xml配置文件,而是使用指定目錄下(或自定義)的配置文件,則須要向configuration()方法中傳遞一個文件路徑的參數便可。
也可使用該對象加載映射文件:
configuration.addResource("cn/eagle/domain/Customer.hbm.xml");
該接口負責初始化Hibernate。它充當數據存儲源的代理,並負責建立Session對象。這裏用到了工廠模式。須要注意的是SessionFactory並非輕量級的,由於通常狀況下,一個項目一般只須要一個SessionFactory就夠,當須要操做多個數據庫時,能夠爲每一個數據庫指定一個SessionFactory。
SessionFactory接口負責Hibernate的初始化和創建Session對象。它在Hibernate中起到一個緩衝區做用,Hibernate能夠將自動生成的SQL語句、映射數據以及某些可重複利用的數據放在這個緩衝區中。同時它還保存了對數據庫配置的全部映射關係,維護了當前的二級緩存。
SessionFactory實例是經過Configuration對象獲取的,其獲取方法以下所示:
SessionFactory sessionFactory = cfg.buildSessionFactory();
它的特色以下:
1. 它是線程安全的,它的同一個實例可以供多個線程共享。
2. 它是重量級的,不能隨意的建立和銷燬它的實例
3. 負責保存和使用全部配置信息,消耗內存資源很是大
4. 保證在web項目中,值建立一個SessionFactory
因爲SessionFactory的這些特色,通常狀況下,一個項目中只須要一個SessionFactory,只有當應用中存在多個數據源時,才爲每一個數據源創建一個SessionFactory實例。所以,在實際項目使用中,一般會抽取出一個HibernateUtils的工具類,用來提供Session對象。
SessionFactory內部還維護了一個鏈接池,若是咱們須要使用第三方的鏈接池如C3P0,那麼須要咱們本身手動進行配置
<!-- 配置C3P0鏈接池 -->
<property name="connection.provider_class">org.hibernate.c3p0.internal.C3P0ConnectionProvider</property>
<!-- 在鏈接池中可用的數據庫鏈接的最少數目 -->
<property name="c3p0.min_size">5</property>
<!-- 在鏈接池中全部數據庫鏈接的最大數目 -->
<property name="c3p0.max_size">20</property>
<!-- 設定數據庫鏈接的過時時間,以秒爲單位,若是鏈接池中的某個數據庫鏈接處於
空閒狀態的時間超過了timeout時間,就會從鏈接池中清除 -->
<property name="c3p0.timeout"></property>
<!-- 每3000秒檢查全部鏈接池中的空閒鏈接,以秒爲單位 -->
<property name="c3p0.idle_test_period">3000</property>
測試C3P0鏈接池
新建測試單元
1 package cn.eagle.test; 2 3 import static org.junit.Assert.*; 4 5 import java.sql.Connection; 6 import java.sql.SQLException; 7 8 import org.hibernate.Session; 9 import org.hibernate.SessionFactory; 10 import org.hibernate.Transaction; 11 import org.hibernate.cfg.Configuration; 12 import org.hibernate.jdbc.Work; 13 import org.junit.After; 14 import org.junit.Before; 15 import org.junit.Test; 16 17 public class HibernateTestC3P0 { 18 private SessionFactory sessionFactory; 19 private Session session; 20 private Transaction transaction; 21 22 @Before 23 public void init() { 24 Configuration configuration = new Configuration().configure(); 25 sessionFactory = configuration.buildSessionFactory(); 26 session = sessionFactory.openSession(); 27 transaction = session.beginTransaction(); 28 } 29 30 @After 31 public void destroy() { 32 transaction.commit(); 33 session.close(); 34 sessionFactory.close(); 35 } 36 37 @Test 38 public void test() { 39 session.doWork(new Work() { 40 41 @Override 42 public void execute(Connection conn) throws SQLException { 43 System.out.println(conn); 44 } 45 46 }); 47 } 48 49 }
Session接口負責執行被持久化對象的CRUD操做(CRUD的任務是完成與數據庫的交流,包含了不少常見的SQL語句)。但須要注意的是Session對象是非線程安全的。同時,Hibernate不一樣於JSP應用中的HttpSession。這裏當使用session這個術語時,其實指的是Hibernate中的session,而之後會將HttpSession對象稱爲用戶session。
Session是應用程序與數據庫之間交互操做的一個單線程對象,是Hibernate運做的中心,它的主要功能是爲持久化對象提供建立、讀取和刪除的能力,全部持久化對象必須在session的管理下才能夠進行持久化操做。
建立SessionFactory實例後,就能夠經過它獲取Session實例。獲取Session實例有兩種方式,
一種是經過openSession()方法,另一種是經過getCurrentSession()方法。兩種方法獲取session的代碼以下所示:
Session session = sessionFactory.openSession();
Session session = sessionFactory.getCurrentSession();
以上兩種獲取session實例方式的主要區別是,採用openSession方法獲取Session實例時,SessionFactory直接建立一個新的Session實例,而且在使用完成後須要調用close方法進行手動關閉。而getCurrentSession方法建立的Session實例會被綁定到當前線程中,它在提交或回滾操做時會自動關閉。
Session是線程不安全的,多個併發線程同時操做一個Session實例時,就可能致使Session數據存取的混亂(方法內部定義和使用Session時,不會出現線程問題)。所以設計軟件架構時,應避免多個線程共享一個Session實例。同時,它也是輕量級的,實例的建立和銷燬不須要消耗太多的資源。它還有給個緩存,即Hibernate的一級緩存,這個緩存主要用於存放當前工做單元加載的對象。
在Session中提供了大量的經常使用方法,具體以下:
1. save()、update()和saveOrUpdate()方法:用於增長和修改對象。
2. delete()方法:用於刪除對象。
3. get()和load()方法:根據主鍵查詢。
4. createQuery()和createSQLQuery()方法:用於數據庫操做對象。
5. createCriteria()方法:條件查詢。
Transaction接口是一個可選的API,能夠選擇不適用這個接口,取而代之的是Hibernate的設計者本身寫的底層事務處理代碼。Transaction接口是對實際事務實現的一個抽象,這些實現包括JDBC事務、JTA中的UserTransaction、甚至能夠是CORBA事務。之因此這樣設計是能讓開發者可以使用一個統一事務的操做界面,使得本身的項目能夠在不一樣的環境和容器之間方便地移植。
Transaction接口主要用於管理事務,它是Hibernate的數據庫事務接口,且對底層的事務接口進行了封裝。Transaction接口的事務對象是經過Session對象開啓的,其開啓方式以下所示。
Transaction tx = session.beginTransaction();
在Transaction接口中,提供了事務管理的經常使用方法,具體以下:
1. commit()方法:提交相關聯的session實例。
2. rollback()方法: 撤銷事務操做。
Session執行完數據庫操做後,要使用Transaction接口的commit()方法進行事務提交,才能真正的將數據庫操做同步到數據庫中。發生異常時,須要使用rollback()方法進行事務回滾,以免數據發生錯誤。所以,在持久化操做後,必須調用Transaction接口的commit()方法和rollback()方法。若是沒有開啓事務,那麼每一個Session操做,都至關於一個獨立的操做。