1. 程式人生 > >hibernate 學習整理 大彙總

hibernate 學習整理 大彙總

一 .hibernate概念:

hibernate應用在javaee 三層框架中的dao層(web 層 --service層--dao層),在dao層實現對資料庫的CRUD操作。hibernate是對jdbc的封裝,使用hibernate的好處,不需要寫jdbc複雜的程式碼,不需要寫sql語句實現。 hibernate是開源的輕量級框架。

版本:hibernate3.x hibernate4.x hibernate5.x 其中4.x不穩定不建議使用

orm: object relational mapping  物件關係對映  hibernate使用的就是orm思想對資料庫進行CRUD操作

簡單說:讓實體類和表進行一一對應關係(實體類名--資料庫表名  實體類中屬性名--表中欄位名)

使用配置檔案來完成這種對應關係

二.配置檔案

hibernate的核心配置檔案

hibernate.cfg.xml  hibernate核心配置檔案 路徑:src目錄下檔名稱固定不變
<hibernate-configuration>  <!-- hibernate 核心配置檔案的跟路徑 -->
    <session-factory> <!--所有的配置資訊都寫在該目錄下 -->

        <!-- 1.連線資料庫-->
        <property name= "connection.driver_class" >com.mysql.jdbc.Driver</property>
        <property name= "connection.url" >jdbc:mysql:///hibernate</property>
        <property name= "connection.username" >root</property>
        <property name= "connnection.password" >root</property>

        <!-- 2. hibernate 其他引數配置 -->
        <property name= "show-sql" >true</property>
        <property name= "format-sql" >true</property>
        <property name= "hibernate.hbm2ddl.auto" >ture</property><!--自動建表,存在更新沒有建立-->
        <property name= "dialect" >org.hibernate.dialect.mysqlDialect</property><!--方言 分頁查詢 mysql 種用limit  oracle中用rownum -->
        <property name= "hibernate.current_session_context_class" >thread</property><!--session是單執行緒物件  所以需要繫結本地執行緒-->

        <!-- 3. mapping 對映檔案引入 -->
        <mapping resource="cn/ss/entity/User.hbm.xml"/><!--路徑用/分割開 因為是檔案路徑-->

hibernate對映配置檔案

hibernate 對映配置檔案 即實體類的對映檔案一般和實體類所在路徑在同一個包下
例如:User.hbm.xml  格式:實體類名+.hbm.xml 固定格式
<!-- 配置類和表的對應關係 -->
<hibernate-mapping><!-- hibernate對映檔案的根目錄-->
    <class name="cn.ss.entity.User" table="t_user">
        <!--所有對應 類屬性和表字段關係都寫在裡面 
            name 屬性: 對映檔案對應的實體類的全路徑
            table 屬性 : 資料庫對應的表名
        -->
         <id name="uid" column="uid">
          <!--id 標識 實體類物件的唯一標識
                name屬性 : 實體類的屬性名 
                column 屬性 : 屬性對應表中是欄位
            -->
            <generator class="native"></generator> 
        </id>

        <!--配置其他 實體類屬性和欄位名對應關係 -->
        <property name="uname" column="uname"></property>
        ... ...
    </class>

主鍵生成策略:

increment: 由long int short 型別使用,由hibernate自動遞增(每次加1) 執行緒不安全 建議測試使用 identity:由DB2 mysql  sql server 等資料庫支援自增長型別的資料庫使用的生成器,要求主鍵定義為自增長生成器型別
sequence:由oracle 等資料庫支援序列的資料庫使用。
native:當使用native hibernate會自動識別資料庫並用對應的主鍵生成策略從而識別主鍵生成識別符
uuid:由hibernate 採用128位uuid演算法 生成的識別符
assignied: 由java 程式生成的識別符,如果預設id沒寫generator 屬性則預設值位assignied

 

三 hibernate 核心api使用

Configuration  SessionFactory Session Transaction

1.Configuration 讀取hibernate核心配置檔案用的類 

Configuration cfg = new Configuraion();
cfg.configure(); //hibernate.cfg.xml 名稱固定 位置固定在src下才可以讀取到

2.SessionFactory 執行過程中建立表,特別消耗資源,建議一個專案只建立一共sesionFactroy物件. 可以建立session 

cfg.buildSessionFactory();

寫在工具類裡面且一個專案只建立一個sessionFactroy 物件的實現程式碼

public class HibernateUtils{//hibernate 工具類

    private static Configuration cfg;
    private static Sessionfactory sessionFactory;
    private static Session session;

    static {//在靜態程式碼塊中建立可以保證類載入的時候只建立一次,保證唯一性
        cfg = new Configuration();
        sessionFactory = cfg.buildSessionFactory();
    }


    public static SessionFactory getSessionFactory(){
        return sessionFactroy;

    }
    public static Session getSession(){
    //session = sessionFactory.OpenSession(); 執行緒不安全不建議使用
    return sessionFactory.getCurrentSession();//繫結本地執行緒 且執行緒安全 不需要手動關閉session     
    //否則寫了會報錯 session.close();

    }

}

3.Session 類相當於jdbc中的connection hibernate中的session是單執行緒的,所以需要繫結本地執行緒

然後呼叫session的方法操作物件

相關方法:

1.獲取物件  get(類名.class,主鍵值)

2.儲存save(物件)

3.修改update(物件)saveOrUpdate(物件)

4.刪除delete(物件)--注意刪除的時候需要先查詢出物件才可以刪除

 

4.Transaction 事務類

只有開啟事務之後 才可以操作session對應的方法 

/**事務開啟*/

Transaction tx = session.beginTransaction();



/** 提交事務**/

tx.commit();


/** 回滾事務**/

tx.rollback();

 事務的特性:原子性 一致性 隔離性 永續性

四 hibermate的對像狀態和快取機制

hibernate對物件由三種狀態:

瞬時態:物件裡即沒有id 主鍵值 ,又沒又在session物件中
    User u = new User(); new出來的都是瞬時態物件 
    u.setname("wangwu");並裡面沒有id

持久態:物件裡即有id主鍵值,又在session的物件中

    持久態物件可以實現立即重新整理,不需要save() update()等
    User u = session.get(User.class,1);
    u.sertname("lisi");

託管態:物件中有id主鍵值,但沒在session的物件中

    User u = new User();
    u.serid(5); // 物件中有id

hibernate的快取:

第一種:一級快取 在session 物件中,生命週期同session,是持久態物件自動更新的依據。實現原理:在建立session物件時會同時建立session的一級快取和一個副本快照區,當session物件呼叫方法得到持久態物件時 首先會到一級快取中查詢是否存在該物件,如果沒有就存放到一級快取中同時複製到副本快照區,當物件修改後,首先到副本區檢視物件是否與該物件一致,如果一致則不做修改,如果不一致則實行自動更新操作,把資料更新到資料庫中

第二種: 二級快取 在sessionFactory物件中,生命週期同sessionFactory,一般很少使用

五 hibernate 表與表之間的關係 及級聯操作

一對多 多對多 一對一

一對多

一對多: 客戶和聯絡人的關係 一個客戶可以有多個聯絡人 但是一個聯絡人只屬於一個客戶 
配置檔案中操作

在一的一方 
客戶方實體類
Customer  class
新增聯絡人Set集合屬性
private Set<LinkMan> setLinkMan = new HashSet<LinkMan>();//無序 唯一性

客戶方對映配置檔案
Customer.hbm.xml
新增set標籤
<set name = "setLinkMan" cascade="save-update,delete" inverse="false" bach-size="10">
<!--cascade屬性:級聯操作  級聯儲存或修改 級聯刪除
 inverse屬性:不放棄關係的維護 預設false  true:表示放棄對關係的維護
這兩個屬性一般都放在一的一方

    bach-size:批量抓起 資料越大 執行sql 越少 效率越高
-->
    <key column = "clid"></key><!-- 聯絡人表外來鍵名稱-->
    <one-to-many class="cn.ss.entity.LinkMan"/>

 </set>


在多的一方 
聯絡人實體類
LinkMan class
新增所屬客戶屬性
private Customer customer;


聯絡人對映配置檔案
LinkMan.hbm.xml
新增many-to-one 標籤
<many-to-one name="customer" class="cn.ss.enetiy.Customer" column="clid"/>


java程式碼
Customer baidu = new Customer();
baidu.sertname("baidu");
LinkMan lucy =  new Link Man();
lucy.setname("lucy");
LinkMna wangcai = new LinkMan();
wangcai.setname("wangcai');

baidu.getSetLinkMan().add(lucy);
baidu.getSetLinkMan().add(wangcai);

//持久態物件 自動更新 不需要save() 方法 實現了級聯儲存操作
級聯刪除類似

多對多

多對多: 使用者的和角色的關係 一個使用者可以有多個角色 ,一個角色也可以有多個使用者
配置中間中操作

在使用者方
使用者實體類
User class
新增角色類set集合
private set<Role> setRole = new HashSet<Role>();

使用者對映配置檔案
User.hbm.xml
新增set標籤
<set name="setRole" table ="user_role" casecade="save-update" inverse="true">
<!--cascade 級聯操作 一般多對多時不會用到級聯刪除 -->
    <!-- table 表示 多對多關係中的第三張表維護多對多關係 -->
    <key column= "userid"></key>
    <many-to-many class="cn.ss.entity.Role" column="roleid"/>
</set>

角色方
角色實體類
Role class
新增使用者set集合
private Set<Use> setUser = new HashSet<User>();

角色對映配置檔案
Role.hbm.xml
新增set標籤
<set name="setUser" table="user_role">
    <key column= "roleid"></key>
    <many-to-many class="cn.ss.entity.User" column="userid"/>
</set>


java程式碼
User u1 = new User();
u1.setname("u1");
User u2 = new User();
u2.setname("u2");

Role r1 = new Role();
r1.setName("r1");
Role r2 = new Role();
r2.setName("r2");
Role r3 = new Role();
r3.setName("r3");


u1.getSetRole().add(r1);
u1.getSetRole().add(r2);
u2.getSetRole().add(r2);
u2.getSetRole().add(r3);

//以下程式碼可以不寫
session.save(u1);
session.save(u2);



六 hibernate其他api查詢物件

Query Crieator SQLQuery

Query物件 使用的是hql語句 只操作實體類和屬性

Query物件  --- HQL查詢
//1.hql語句 建立
String hql = "from User"; //from+實體類  查詢所有

//2 建立Query物件
Query query = session.createQuery(hql);

//3.呼叫物件方法返回結果
List <User>  list = query.list();


hql語句:
1.查詢所有 “form User”  from+實體類類名
2.條件查詢 "from User where uid = ?" 條件語句where+實體類屬性名=? ?是佔位符
    需要設定值 用query.setParameter(下標從0開始,對應屬性值);
    如果多條用 List<User> list = query.list();  
    如果唯一值 Object obj = query.uniqueResult(); 注意long型資料
3.模糊查詢 “form User where name like ?”
    ? 佔位符值設定:query.setParameter(下標從0開始,“%白%”);
4.排序查詢 “from User Order by uid” //form+實體類名+order by +屬性名 asc/desc;
5.分頁查詢 使用的是query物件的兩個方法
    query.setFirstResult(0);//從0開始查
    query.setMaxResults(3);//每頁查詢3條記錄
6.投影查詢 “select uid,unmae from User” //select+屬性名1,屬性名2 form+實體類名;
    注意 投影查詢得到的list集合每個物件是Object[] 陣列/或object 物件
7.聚集函式查詢 count max min sum avg 等sql函式
    "select count(*) from User" //select +聚集函式+form+實體類名;




HQL多表查詢

內連結  左外連線 右外連線

特有的查詢:迫切內連結  迫切左外連線 (沒有迫切右外連線)

HQL多表查詢
1.內連線
String hql = "from Customer c inner join c.setLinkMan" ;//用到都是本類中的屬性值
Query query = session.createQuery(hql);
List<Objec[]> list = query.list();//返回的list集合的每個元素是Object[] 陣列

2.迫切內連線
迫切內連結和內連線底層實現是一樣的
區別:內連結返回的是list的object[] 陣列 ,但是迫切內連線返回的list 每個元素是物件
String hql = "from Customer c inner join fetch c.setLinkMan"; //迫切內連線

3.左外連線
Sting hql = "from Customer c left outer join c.setLinkMan";

4.迫切左外連線
Sting hql = "from Customer c left outer join fetch c.setLinkMan";
同上特性
區別:左外連結返回的是list的object[] 陣列 ,但是迫切左外連線返回的list 每個元素是物件

5.右外連線 此處不寫了同上

 

Crieator 物件沒有sql hql 等對應的語句查詢只有對應物件及方法作為條件進行查詢

Criteria --QBC查詢

//1.建立Criteria物件
Criteria criteria = session.createCriteria(User.class);//引數位類的位元組碼物件
//2.呼叫criteria物件方法
List<User> list = criteria.list();
//3.增強for迴圈檢視
for(User user : list){
    syso(user.getid()+ user.getname());

}

1.查詢所有
criteria.list();
2.條件查詢  使用criteria的add()方法 引數為物件Restriction(屬性名,屬性值)
    criteria.add(Restriction.eq("uid",1));

3.模糊查詢
criteria.add(Restriction.like("uname","%白%");

4.排序查詢
criteria.addOrder(Order.asc("uid")); //正序 Order.desc("uname") 倒序

5.分頁查詢
criteria.setFirstResult(0);//從0開始查詢
criteria.setMaxResult(3);//每頁3條記錄
開始位置計算公式 : (當前頁-1)*每頁記錄

6.統計查詢
criteria.setProjection(Projection.rowcount);
Object obj = criteria.uniqueResult();
Long lobj = (Long)obj;
int count = lobj.intValue();
7.離線查詢
Detachedcriteria dc  = Detachedcriteria.forClass(User.class);
Criteria c = dc.getExectableCriteria(session);
List<User> list = c.list();

SQLQuery 查詢

 SQLQuery 查詢
//建立SQLQuery物件
SQLQuery sq = session.createSQLQuery(sql);//sql 為資料庫sql 語句
//執行物件方法返回結果
List list = sq.list();//預設返回的list集合是陣列形式 Object[]
//遍歷
for(Object[] obj : list){
    syso(Arrays.toString(obj));

}

將結果轉換成每個部分是物件
sqlquery.addEntity(User.class);
List<User> list = sqlquery.list();
for(User u : list){

    syso(u);
}