Hibernate-部分知識點概述(持續更新)

Hibernate

面向對象操作模型數據庫->阻抗不匹配

ORM(Object Relation Mapping->對象關係映射)->完成對象與關係之間的轉換

主流ORM框架:Hibernate Toplink OJB


(一)

簡單使用步驟:

詳見:http://blog.csdn.net/qq_28796345/article/details/52513814

(1)創建項目

(2)導入jar包

(3)創建實體對象Usre

(4)創建User.hbm.xml映射文件(於相應包下)

(5)創建配置文件於src下(hibernate.cfg.xml)

(6)創建測試類(初始化hibernate)


hibernate.cfg.xml:

<!DOCTYPE hibernate-configuration PUBLIC

    "-//Hibernate/Hibernate Configuration DTD 3.0//EN"

    "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">


<hibernate-configuration>

    <session-factory>

    

        <!-- 數據庫驅動 -->

        <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>

        <!-- 所用數據庫 -->

        <property name="dialect">org.hibernate.dialect.MySQLDialect</property>

        <!-- 數據庫url -->

        <property name="connection.url">jdbc:mysql:///hibernate</property>

        <!-- 數據庫用戶名 -->

        <property name="connection.username">root</property>

        <!-- 用戶密碼 -->

        <property name="connection.password">0707</property>

        <!-- 創建表 -->

        <property name="hbm2ddl.auto">create</property>

        <!-- 映射文件位置 -->

        <mapping resource="com/sw/hibernate/domain/User.hbm.xml"/>

    </session-factory>

    

</hibernate-configuration>


User.hbm.xml:

<?xml version="1.0"?>

<!DOCTYPE hibernate-mapping PUBLIC

    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"

    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping

    package="com.sw.hibernate.domain">


    <class name="User" table="user">

        

        <!-- 數據庫表主鍵 column指定字段名 -->        

        <id name="id" column="id">

            <generator class="native"/>

        </id>

        <!-- property爲屬性 -->

        <property name="name" column="name"/>

        <property name="birthday"/>

        

    </class>

    

</hibernate-mapping>

工具類

初始化:

/*

 *@Author swxctx

 *@time 2016年9月12日

 */

package com.sw.util;


import org.hibernate.Session;

import org.hibernate.SessionFactory;

import org.hibernate.cfg.Configuration;


public final class HibernateUtil {

    //工具類 用於初始化hibernate(一次初始化)

    private static SessionFactory sessionFactory;

    private HibernateUtil(){

        

    }

        static{

            //需要進行一次初始化

            Configuration cfg=new Configuration();

            cfg.configure();//讀取配置文件

            //初始化後得到sessionfactory

            sessionFactory = cfg.buildSessionFactory();//類似於DriverManager

        }

    public static SessionFactory getSessionFactory() {

        return sessionFactory;

    }

    

    public static Session getSession(){

        return sessionFactory.openSession();

    }

}
執行方法封裝:

/*

 *@Author swxctx

 *@time 2016年9月12日

 */

package com.sw.util;


import org.hibernate.HibernateException;

import org.hibernate.Session;

import org.hibernate.Transaction;


import com.sw.hibernate.domain.User;


public class Tooladd {

    static void addUser(User user){

        Session s=null;

        Transaction tx=null;

        try {

            //初始化

            s=HibernateUtil.getSession();

            //操作數據

            tx=s.beginTransaction();

            //保存對象

            s.save(user);

            //提交

            tx.commit();

        } catch (HibernateException he) {

            // TODO: handle exception

            if(tx!=null){

                tx.rollback();//回滾

                throw he;//拋出異常

            }

        }finally{

            if(s!=null){

                s.close();//關閉

                s=null;

            }

        }

    }

    

    static void addUser1(User user){

        Session s=null;

        Transaction tx=null;

        try {

            //初始化

            s=HibernateUtil.getSession();

            //操作數據

            tx=s.beginTransaction();

            //保存對象

            s.save(user);

            //提交

            tx.commit();

        } finally{

            if(s!=null){

                s.close();//關閉

                s=null;

            }

        }

    }

}



Session接口:

get(查詢)、load(更新)、persist(保存)方法


實體對象的三種狀態與saveOrUpdate(根據id的值來確定使用save還是update方法)方法

(1)瞬時-數據庫沒有數據與之對應,超過作用域會被jvm垃圾回收。

(2)持久-數據庫沒有記錄,並且session並沒有關閉,與session有關

(3)脫管-與session沒有關係,與數據庫表有對應


HQL與Criteria


1、Hql

實例:

//查詢

static void query(String name){

    Session s=null;

    try {

        //初始化

        s=HibernateUtil.getSession();

        String hql="from User as user where user.name=?";

        Query query=s.createQuery(hql);

        query.setString(0, name);

        List<User> list=query.list();

//            Object ob=query.uniqueResult();//返回object類型

        for(User user:list){

            System.out.println(user.getName());

        }

    }finally{

        if(s!=null){

            s.close();//關閉

            s=null;

        }

    }

}  

注:在hbm.xml文件中,應該避免屬性名與數據庫關鍵字衝突,若衝突,則在前加上反引號即可。


hql的命名參數與Query接口的分頁查詢:

from User as user where user.name=?

如上語句,如果在字段過多時則不會適用。

解決辦法:使用命名參數(爲用戶定義名字)

from User as user where user.name=:name

query.string("name",name);

Query


分頁:

Query query=s.createQuery(hql);

//從第一頁開始取結果,每頁取十條

query.setFirstResult(0);//實現分頁 第一條

query.setMaxResults(10);//每頁十條


2、Criteria(條件查詢)

實例:

static void cri(String name){

    Session s=null;

    try {

        //初始化

        s=HibernateUtil.getSession();

        Criteria c=s.createCriteria(User.class);

        //查找name對應的數據

        c.add(Restrictions.eq("name", name));//傳入的參數(約束條件)

        c.setFirstResult(0);//分頁

        c.setMaxResults(10);

        List<User> list=c.list();

        User u=(User)c.uniqueResult();

        for(User user:list){

            System.out.println(user.getName());

        }

    }finally{

        if(s!=null){

            s.close();//關閉

            s=null;

        }

    }

}


(二)

關聯

詳見:點擊打開鏈接

多對一關聯關係的映射與原理

一對多

多對一

一對一

多對多(使用中間表)->執行速率較慢,不常用

多對多關聯關係的檢索

兩個組件(對象)關聯


級聯操作-對相應的對象進行統一的操作(保存時都保存、刪除時將其數據都刪除等)

<set name="em" cascade="save-update">

    <key column="depart_id"></key>

    <one-to-many class="Employee"/>

</set>


inverse屬性(有序集合不能出現,不會放棄關係維護)

用於一對多中->一放棄維護與多個的關聯關係

放棄維護關係->不再更新外鍵

<list name=" " inverse="true">


(四)

繼承映射

<?xml version="1.0"?>

<!DOCTYPE hibernate-mapping PUBLIC

    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"

    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping

    package="com.sw.hibernate.domain">


    <class name="Employee" table="Employee" discriminator-value="0">

        

        <!-- 數據庫表主鍵 column指定字段名 -->        

        <id name="id" column="id">

            <generator class="native"/>

        </id>

        

        <discriminator column="type" type="int"/>

        

        <!-- property爲屬性 -->

        <property name="name" column="name"/>

        

        <!-- Department 多對一-->

        <!-- depart_id 外鍵  對應於department的id-->

        <many-to-one name="depart" column="depart_id" property-ref="id"/>

        

        <!-- 對象映射 -->

        <subclass name="Skiller" discriminator-value="1">

            <property name="skill"/>

        </subclass>

        <subclass name="Sales" discriminator-value="2">

            <property name="sell"/>

        </subclass>

    </class>

    

</hibernate-mapping>



每個子類映射到一張表(效率低,結構清晰)

<!-- 每個子類對應一張表 -->

<joined-subclass name="Skiller" table="skiller">

    <key column="emp_id"/>

    <property name="skill"/>

</joined-subclass>

<joined-subclass name="Sales" table="sales">

    <key column="emp_id"/>

    <property name="sell"/>

</joined-subclass>


繼承映射->1、一個類繼承體系一張表 2、每個子類各一張表

<union-subclass>->將每個表都保存完整的信息(每個子類一張表)


(五)

懶加載:Hibernate.initialize(對象)->Domain非final;

通過asm.jar與cglib.jar兩個包實現懶加載。


一對一懶加載(默認情況下hibernate會使用懶加載)->查詢主對象時不會進行懶加載

查詢重對象時,會啓用懶加載

除多對一以外,儘量不要禁用懶加載,如果禁用會產生一些意想不到的錯誤。

懶加載並不能區分空集合,當與數據表結構衝突時(數據爲空),則會出現問題。


能夠懶加載的對象都是被改寫過的代理對象,當相關聯的session沒有關閉時,訪問這些懶加載

對象(代理對象)的屬性(getId和getClass除外)。hibername會初始化這些代理,或用hibernate

.initialize(proxy)來初始化代理對象;當相關聯的session關閉後,再訪問懶加載的對象將

出現異常。


屬性亦可進行懶加載。


(六)

1、一級緩存

緩存->第一次讀取時將其存放到內存中,第二次直接從內存讀取,提高了性能。

(1)將數據放入緩存中->使用map map.put(key,user);

(2)從緩存中取出數據

(3)刪除無效數據 map.remove(key);


Session存在緩存,隨着session的關閉而消失。

第一次get(獲取)時,將數據放入緩存。

session.evict(user);//將user對象從session緩存中清除

session.clear();//清除所有緩存

使用一級緩存需要防止數據溢出(並不會限制放置的個數,直到內存溢出)

一級緩存的存在時間較短(一個請求內),所以會導致數據失效等問題,使用二級緩存可以解決這一問題。


2、二級緩存(SessionFactory級共享)

交給第三方框架處理。

通過配置文件hibernate.cfg.xml進行處理:

<!-- 打開二級緩存 -->

<property name="cache.use_second_level_cache">true</property>

 <!-- 打開查詢緩存 -->

<property name="cache.use_query_cache">true</property>

<!-- 所使用的緩存機制 -->

<property name="cache.provider_class">org.hibernate.cache.OSCacheProvider</property>

<!-- 指定需要緩存的類 -->

<class-cache usage="read-only" class="cn/itcast/hibernate/domain/User"/>


指定需要緩存的類,除了在這裏指定外,亦可在映射文件中進行配置指定:

<cache usge="read-only"/><!--放置於class內部-->


hibernate尋找數據步驟->先到以及緩存尋找,如果以及緩存不存在該數據,則到二級緩存進行尋找,

若二級緩存仍然不存在,則到數據庫中進行尋找。


分佈式緩存與中央緩存:

使用緩存的條件:

(1)讀取次數大於修改

(2)數據量不能超過內存量

(3)對數據要有獨享的控制

(4)可以容忍出現無效數據


(七)

事務

JDBC Transaction(單步事務,使用一個庫)

JTA Transaction(分佈式事務處理,使用多個庫)->跨數據庫的事務,由應用JTA容器實現。


openSession()->

getCurrentSession()->獲取當前session


ThreadLocal


OpenSessionInView


Hibernate-Mapping->多種屬性(隱藏屬性的使用)->schema


使用class類可以定義一個持久化類。


鑑別器


property屬性亦具有懶加載功能。


Hibernate映射類型。


Session是非線程安全的,生命週期較短,一般不會超過一個請求。代表一個和數據庫的連接。

SessionFactory是線程安全的,聲明週期較長,一般在整個系統內都是有效的。

保存着喝數據庫連接的相關信息。


批量更新

1、flush使一級緩存與數據庫同步。

Session.flush();

當數據量較大時,在調用clear之前先調用flush。


2、StatelessSession接口

不和一二級緩存交互,也不觸發任何事件。


N+1次查詢與懶加載。

N條記錄會出現N+1此查詢記錄。


攔截器

監聽器

本地sql查詢與命名查詢

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章