3.hibernate

1. hibernate框架java

框架的含義:mysql

  • 1.框架是用來提升開發效率的
  • 2.封裝了好了一些功能.咱們須要使用這些功能時,調用便可.不須要再手動實現.
  • 3.因此框架能夠理解成是一個半成品的項目.只要懂得如何駕馭這些功能便可.

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具備如下優點:

  • Hibernate對JDBC訪問數據庫的代碼作了輕量級封裝,大大簡化了數據訪問層繁瑣的重複性代碼,而且減小了內存消耗,加快了運行效率。
  • Hibernate是一個基於JDBC的主流持久化框架,是一個優秀的ORM實現,它很大程度的簡化了DAO(Data Access Object,數據訪問對象)層編碼工做。
  • Hibernate的性能很是好,映射的靈活性很出色。它支持不少關係型數據庫,從1對1到多對多的各類複雜關係。
  • 可擴展性強,因爲源代碼的開源以及API的開放,當自己功能不夠用時,能夠自行編碼進行擴展。

orm分4級
hibernate屬於4級:徹底面向對象操做數據庫
mybatis屬於2級
dbutils屬於1級

Hibernate5.0.7的目錄介紹:

  • documentation文件夾:存放Hibernate的相關文檔,包括參考文檔的API文檔。
  • lib文件夾:存放Hibernate編譯和運行所依賴的JAR包。其中required子目錄下包含了運行Hibernate5項目必須的JAR包。
  • project文件夾:存放Hibernate各類相關的源代碼。

 

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
  • 建立映射文件

實體類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>
Customer.hbm.xml
  • 建立Hibernate的核心配置文件

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>
hibernate.cfg.xml

 

3. Hibernate配置文件詳解

在以上部分中,咱們已經接觸過Hibernate的映射文件和配置文件。接下來,將對這些文件進行詳細的講解。

  • 映射文件Customer.hbm.xml用於向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

  • 核心配置文件hibernate.cfg.xml包含了鏈接持久層與映射文件所需的基本信息,其配置文件有兩種格式,具體以下:
    • 一種是properties屬性文件格式的配置文件,它使用鍵值對的形式存放信息,默認文件名稱爲Hibernate.properties;
    • 另外一種是XML格式的配置文件,XML配置文件的默認名稱爲hibernate.cfg.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

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");

  • SessionFactory

該接口負責初始化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 }
HibernateTestC3P0

  • Session

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

  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操做,都至關於一個獨立的操做。

相關文章
相關標籤/搜索