hibernate框架學習

hibernate入門

1、ORM框架:object relational mapping用於實現面向對象編程語言裏不同數據類型系統的數據之間的轉換。
Hibernate是一個數據持久化層的ORM框架.它是輕量級的JavaEE應用的持久層解決方案,是一個關係數據庫ORM框架
這裏寫圖片描述

ORM 就是通過將Java對象映射到數據庫表,通過操作Java對象,就可以完成對數據表的操作
Hibernate提供了對關係型數據庫增刪改成操作

hibernate的優點:

  • Hibernate對JDBC訪問數據庫的代碼做了封裝,大大簡化了數據訪問層繁瑣的重複性代碼
  • Hibernate是一個基於jdbc的主流持久化框架,是一個優秀的orm實現,它很大程度的簡化了dao層編碼工作 session.save(User);
  • Hibernate使用java的反射機制
  • Hibernate的性能非常好,因爲它是一個輕量級框架。映射的靈活性很出色。它支持很多關係型數據庫,從一對一到多對多的各種複雜關係

入門案例:

1、編寫流程

  • 導入jar包
  • 創建數據庫和表
  • 編寫核心配置文件(hibernate.cfg.xml)–> 配置獲得鏈接等參數
  • 編寫映射文件 hibernate mapping(*.hbm.xml)
  • 使用api測試

一、創建表

create database h_db;
use h_db;
create table t_user(
  id int auto_increment primary key,
  username varchar(50),
  password varchar(30)
);

二、導入jar包:

  • hibernate3.jar
  • \lib\required
  • jap規範:lib\jpa
  • mysql驅動包

包的含義:
這裏寫圖片描述

三、編寫JavaBean + 映射文件

package com.zeroyoung.domain;

public class User {
    /*
     * create table t_user(
          id int auto_increment primary key,
          username varchar(50),
          password varchar(30)
        );
     */
    private Integer uid;
    private String username;
    private String password;
    public Integer getUid() {
        return uid;
    }
    public void setUid(Integer uid) {
        this.uid = uid;
    }
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
    @Override
    public String toString() {
        return "User [uid=" + uid + ", username=" + username + ", password="
                + password + "]";
    }
}

在javabean的同一目錄下創建一個User.hbm.xml的文件
這個xml的文件的約束在hibernate3.jar/org.hibernate/hibrenate-mapping-30.dtd

<?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">

<!-- ORM元數據,表對象關係映射文件
    package:配置改配置文件中類所在的包 -->
<hibernate-mapping >
    <!-- class: 配置實體與表的關係
        name : 填寫實體的完整類名
        table: 與實體對應表的名稱
        dynamic-insert:動態插入 默認值是false
                        true=>如果字段值爲null,不參與insert語句
         dynamic-update:動態更新  默認值"false"
                        true=> 沒改動過的屬性,將不會生成到update語句中
     -->
    <class name="com.zeroyoung.domain.User" table="t_user">
        <!-- 主鍵的聲明 -->
        <!-- id: 配置實體與表中 id對應
            name: user對象中標識主鍵的屬性名稱
            column: 主鍵在表中的列名
            length: 列的數據長度
            unsaved-value(不常用): 指定主鍵爲什麼值時,當做null來處理.
            access(強烈推薦不要用):field 那麼在操作屬性時,會直接操作對應的字段而不是get/set方法
         -->
        <id name="uid" column="id" length="255">
            <!-- 主鍵生成策略,由數據庫控制 -->
            <!-- generator:主鍵生成策略
                    1.increment  數據庫自己生成主鍵. 先從數據庫中查詢最大的ID值,將ID值加1作爲新的主鍵
                    2.identity  依賴於數據的主鍵自增功能
                    3.sequence  序列,依賴於數據中的序列功能(Oracle).
                    4.hilo(純瞭解,永遠用不到) : Hibernate自己實現序列的算法,自己生成主鍵. (hilo算法 )
                    5.native 自動根據數據庫判斷,三選一. identity|sequence|hilo
                    6.uuid  生成32位的不重複隨機字符串當做主鍵
                    7.assigned 自己指定主鍵值. 表的主鍵是自然主鍵時使用.

             -->
            <generator class="native"></generator>
        </id>
        <!-- property : 實體中屬性與表中列的對應
             name : 實體中屬性名稱
             column : 表中列的名稱
             length : 數據長度
             precision: 小數點後的精度
             scale: 有效位數
             insert(一般不用): 該屬性是否加入insert語句.
             update(一般不用): 該屬性是否加入update語句.
             not-null : 指定屬性的約束是否使用 非空
             unique : 指定屬性的約束是否使用 唯一
         -->
        <property name="username" column="username"/>
        <property name="password" column="password"/>
    </class>
</hibernate-mapping>   

四、編寫核心配置文件
在src目錄下面編寫配置文件hibernate.cfg.xml

<?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>
        <!-- property:元素用於配置hibrenate中的屬性,方式爲鍵值對 -->

        <!-- hibernate.connection.driver_class:數據庫連接驅動 -->
        <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>

        <!--hibernate.connection.username: 數據庫連接用戶名 -->
        <property name="hibernate.connection.username">root</property>

        <!-- 數據庫連接密碼 -->
        <property name="hibernate.connection.password">root</property>

        <!-- 數據庫連接的地址,路徑 -->
        <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/h_day01_db</property>

        <!-- 操作數據庫時,會向控制檯打印sql語句 -->
        <property name="show_sql">true</property>

        <!-- 格式化sql語句 -->
        <property name="format_sql">true</property>

        <!-- hbm2ddl.auto: 生成表結構的策略配置
            update(最常用的取值): 如果當前數據庫中不存在表結構,那麼自動創建表結構. 
                    如果存在表結構,並且表結構與實體一致,那麼不做修改
                    如果存在表結構,並且表結構與實體不一致,那麼會修改表結構.會保留原有列.
             create(很少):無論是否存在表結構.每次啓動Hibernate都會重新創建表結構.(數據會丟失)
             create-drop(極少): 無論是否存在表結構.每次啓動Hibernate都會重新創建表結構.每次Hibernate運行結束時,刪除表結構.
             validate(很少):不會自動創建表結構.也不會自動維護表結構.Hibernate只校驗表結構. 如果表結構不一致將會拋出異常.
         -->
        <property name="hbm2ddl.auto">update</property>

        <!-- 數據庫方言配置 
         org.hibernate.dialect.MySQLDialect (選擇最短的)
         -->
        <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>

        <!-- hibernate.connection.autocommit: 事務自動提交  -->
        <property name="hibernate.connection.autocommit">true</property>

        <!-- 將Session與線程綁定=> 只有配置了該配置,才能使用getCurrentSession -->
        <property name="hibernate.current_session_context_class">thread</property>

        <!-- 引入ORM 映射文件 
            填寫src之後的路徑
         -->
        <mapping resource="com/zeroyoung/domain/User.hbm.xml"/>
    </session-factory>
</hibernate-configuration>

五、測試:

    @Test
    public void tet() {
        // 1.加載配置文件獲取核心配置核心對象
        // 1.1 調用configure() 方法=> 加載src下名爲hibernate.cfg.xml
        // 1.2 如果配置文件不符合默認加載規則.我們可以調用
        // new Configuration().configure(file); 通過file加載
        // new Configuration().configure(path); 通過路徑加載
        // 1.3 可以通過Configuration對象加載 映射文件(不推薦)
        // 推薦hibernate.cfg.xml 使用 mapping 屬性引入配置文件
        // 規範: 1>orm映射文件名稱與實體的簡單類名一致
        // 2>orm映射文件 需要與實體的類在同一包下
        Configuration config = new Configuration().configure();

        // 2.獲取sessionFactory,相當於連接池
        // 根據Configuration 配置信息創建 SessionFactory

        SessionFactory factory = config.buildSessionFactory();
        // 3.獲取會話session,相當於serlvet重點connection
        // 3.1 openSession => 獲得一個全新的Session對象
        // 3.2 getCurrentSession => 獲得與當前線程綁定的session對象
        // 調用getCurrentSession 需要加上一個配置: <property
        // name="hibernate.current_session_context_class">thread</property>
        Session session = factory.openSession();

        User u = new User();
        u.setPassword("1233");
        u.setUsername("zhon");
        // 4.操作數據庫
        session.save(u);

        // 5.關閉資源
        session.close();
        factory.close();
    }

api詳解

  • Configuration配置對象
    我們編寫的hibernate.cfg.xml配置文件需要使用 Configuration來加載,加載的方式有幾種。常見的使用方式如下:
Configuration config = new Configuration().configure();

這裏configure()方法就是加載src下名爲hibernate.cfg.xml
同時,它也提供了有參數的構造方法來使用,當我們的配置文件的不符合默認加載規則,我們可以調用如下的方法

  • new Configuration().configure(file); 通過file加載
  • new Configuration().configure(path); 通過路徑加載

####SessionFactory工廠
SessionFactory 相當於java web連接池,用於管理所有session
獲得方式:SessionFactory factory = config.buildSessionFactory();
sessionFactory hibernate緩存配置信息 (數據庫配置信息、映射文件,預定義HQL語句 等)
SessionFactory線程安全,可以是成員變量,多個線程同時訪問時,不會出現線程併發訪問問題。
提供api:
打開一個新的會話:

Session session = factory.openSession();

這裏得到的session是重新創建的session會話

得到當前線程綁定的session

Session session = getCurrentSession()

這裏是使用當前線程綁定的session會話,如果當前線程沒綁定session則先創建一個session對象,然後綁定之後返回。
要想使用當前線程綁定session就需要在配置文件中加上這句話:

<property name="hibernate.current_session_context_class">thread</property>

這個方法主要是跟事務的提交有關係,事務關閉時,會自動把與當前線程關聯的session關閉,並刪除


Session 會話

Session 相當於 JDBC的 Connection – 會話,我們是通過session來操作po(persistent object ,用於與數據庫交互數據。–dao層 (JavaBean + hbm ))對象的
session是單線程的,線程不安全,不能編寫成員變量
session中的幾個api方法:

  • save 保存
  • update 更新
  • delete 刪除
  • get 通過id查詢,如果沒有 null
  • load 通過id查詢,如果沒有拋異常
  • createQuery(“hql”) 獲得Query對象
  • createCriteria(Class) 獲得Criteria對象

保存對象上面的例子已近說明,更新對象那個的方法如下

        User user = (User) session.get(User.class, 1);
        user.setUsername("湯姆");
        session.update(user);

刪除:

        // 先查詢出你要修改的對象
        User user = (User) session.get(User.class, 1);
        // 刪除
        session.delete(user);

get查詢:
第一個參數時候javabean,第二個是id的值

        // 先查詢出你要修改的對象
        User user = (User) session.get(User.class, 2);

load查詢:

// 先查詢出你要修改的對象
User user = (User) session.load(User.class, 2);

load與get的區別:
get方法被調用時立刻 發送sql語句查詢、load調用時並沒有查詢數據庫,當我們需要使用該對象的時候,才查詢數據

createQuery編寫查詢語句
查詢所有的用戶

        // HQL語言 => Hibernate Query Language
        // createQuery 傳入hql語句查詢,完整類名字
        // 相當於select * from t_user;
        Query query = session.createQuery("from com.zeroyoung.domain.User");
        List<User> list = query.list();
        System.out.println(list);

Criteria查詢所有(一般很少使用)

// Criteria 查詢 => Hibernate獨創的面向對象的查詢=> 無語句
Criteria criteria = session.createCriteria(User.class);
List<User> list = criteria.list();

支持原生的sql語句查詢:

        // 原生的Sql查詢
        SQLQuery query = session.createSQLQuery("select * from t_user");
        // addEntity 將查詢結果封裝到指定對象中
        query.addEntity(User.class);
        List<User> list = query.list();

事務Transaction

開啓事務 beginTransaction()
獲得事務 getTransaction()
提交事務:commit()
回滾事務:rollback()

try{
   //開啓
   //session操作
   //提交
} catch(e){
   //回滾
}

query對象

通過createQuery()方法,我們會得到一個query對象,它能幫助我們完成一些列的事情。
api:

  • list() 查詢所有
  • uniqueResult()獲取一個結果,如果沒有查到返回null,如果查詢到多條拋出異常
  • setFirstResult(int)分頁,開始索引的數startIndex
  • setMaxResults(int) 分頁,每頁顯示個數 pageSize
        Query query = session.createQuery("from com.zeroyoung.domain.User");

        // 分頁 limit index,count;
        // 指定結果從第幾個開始拿
        query.setFirstResult(0);
        // 指定拿幾個
        query.setMaxResults(2);

        // query.list() 將hql語句執行,並返回結果(多行)
        List<User> list = query.list();
        System.out.println(list);

        //uniqueResult 將hql語句執行,並返回結果(一行),用於在createquery中添加條件
        //User u = (User) query.uniqueResult();
        //System.out.println(u);

Criteria對象

QBC(query by criteria),hibernate提供純面向對象查詢語言,提供直接使用PO對象進行操作。
獲得方式:Criteria criteria = session.createCriteria(User.class);

        criteria.add(Restrictions.eq("username", "tom"));
//      Restrictions.gt(propertyName, value)        大於
//      Restrictions.ge(propertyName, value)    大於等於
//      Restrictions.lt(propertyName, value)    小於
//      Restrictions.le(propertyName, value)    小於等於
//  Restrictions.like(propertyName, value)  模糊查詢,注意:模糊查詢值需要使用 % _

創建一個工具類

public class H3Utils {

    // 會話工廠,整個程序只有一份。
    private static SessionFactory factory;

    static{
        //1 加載配置
        Configuration config = new Configuration().configure();

        //2 獲得工廠
        factory = config.buildSessionFactory();
//3 關閉虛擬機時,釋放SessionFactory
            Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {

            @Override
            public void run() {
                System.out.println("虛擬機關閉!釋放資源");
                sf.close();
            }
        }));
    }


    /**
     * 獲得一個新的session
     * @return
     */
    public static Session openSession(){
        return factory.openSession();
    }

    /**
     * 獲得當前線程中綁定session
     * * 注意:必須配置
     * @return
     */
    public static Session getCurrentSession(){
        return factory.getCurrentSession();
    }
}

配置文件詳解

<?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>
        <!-- property 元素用於配置Hibernate中的屬性
            鍵:值 
          -->
          <!-- hibernate.connection.driver_class : 連接數據庫的驅動  -->
        <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
          <!-- hibernate.connection.username : 連接數據庫的用戶名 -->
        <property name="hibernate.connection.username">root</property>
          <!-- hibernate.connection.password : 連接數據庫的密碼 -->
        <property name="hibernate.connection.password">1234</property>
          <!-- hibernate.connection.url : 連接數據庫的地址,路徑 -->
        <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/EE19Day01</property>

        <!-- show_sql: 操作數據庫時,會 向控制檯打印sql語句 -->
        <property name="show_sql">true</property>
        <!-- format_sql: 打印sql語句前,會將sql語句先格式化  -->
        <property name="format_sql">true</property>
        <!-- hbm2ddl.auto: 生成表結構的策略配置
             update(最常用的取值): 如果當前數據庫中不存在表結構,那麼自動創建表結構. 
                    如果存在表結構,並且表結構與實體一致,那麼不做修改
                    如果存在表結構,並且表結構與實體不一致,那麼會修改表結構.會保留原有列.
             create(很少):無論是否存在表結構.每次啓動Hibernate都會重新創建表結構.(數據會丟失)
             create-drop(極少): 無論是否存在表結構.每次啓動Hibernate都會重新創建表結構.每次Hibernate運行結束時,刪除表結構.
             validate(很少):不會自動創建表結構.也不會自動維護表結構.Hibernate只校驗表結構. 如果表結構不一致將會拋出異常.
          -->
        <property name="hbm2ddl.auto">update</property>

        <!-- 數據庫方言配置 
             方言:爲不同的數據庫,不同的版本,生成sql語句(DQL查詢語句)提供依據 
             mysql 字符串 varchar
             orcale 字符串 varchar2
        -->

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



        <!-- hibernate.connection.autocommit: 事務自動提交  -->
        <property name="hibernate.connection.autocommit">true</property>
        <!-- 將Session與線程綁定=> 只有配置了該配置,才能使用getCurrentSession -->
        <property name="hibernate.current_session_context_class">thread</property>
        <!-- 引入ORM 映射文件 
            填寫src之後的路徑
         -->
        <mapping resource="com/itheima/a_hello/User.hbm.xml"/>
    </session-factory>
</hibernate-configuration>

Hibernate中持久化類–javabean

1、javabean的編寫規範

  • 提供一個無參數 public訪問控制符的構造器
  • 提供一個標識屬性,映射數據表主鍵字段
  • 所有屬性提供public訪問控制符的 set get 方法(javaBean)
  • 標識屬性應儘量使用基本數據類型的包裝類型
  • 不要用final修飾實體 (將無法生成代理對象進行優化)

2、持久化對象的唯一標識OID

  • java按地區區分同一個類的不同對象
  • 關係數據庫用主鍵區分同一條記錄
  • Hibernate使用OID來建立內存中的對象和數據庫中記錄的對應關係
    結論:對象的OID和數據庫的表的主鍵對應。爲保證OID的唯一性,應該讓Hibernate來爲OID付值
區分自然主鍵和代理主鍵

一、主鍵需要具備:

  • 不爲空
  • 不能重複
  • 不能改變

    自然主鍵:在業務中,某個屬性符合主鍵的三個要求.那麼該屬性可以作爲主鍵列.
    代理主鍵:在業務中,不存符合以上3個條件的屬性,那麼就增加一個沒有意義的列.作爲主鍵.

基本數據與包裝類型

  • 基本數據類型和包裝類型對應hibernate的映射類型相同
  • 基本類型無法表達null、數字類型的默認值爲0。
  • 包裝類默認值是null。當對於默認值有業務意義的時候需要使用包裝類。

數據類型的對應圖標表
這裏寫圖片描述


普通屬性

<hibernate-mapping> 
            package 用於配置PO類所在包
                例如: package="com.itheima.d_hbm"
        <class> 配置 PO類 和 表 之間對應關係
            name:PO類全限定類名
                例如:name="com.itheima.d_hbm.Person"
                如果配置 package,name的取值可以是簡單類名 name="Person"
            table : 數據庫對應的表名
            dynamic-insert="false" 是否支持動態生成insert語句
            dynamic-update="false" 是否支持動態生成update語句
                如果設置true,hibernate底層將判斷提供數據是否爲null,如果爲null,insert或update語句將沒有此項。
        普通字段
            <property>
                name : PO類的屬性
                column : 表中的列名,默認name的值相同
                type:表中列的類型。默認hibernate自己通過getter獲得類型,一般情況不用設置
                    取值1: hibernate類型
                        string 字符串
                        integer 整形
                    取值2: java類型 (全限定類名)
                        java.lang.String 字符串
                    取值3:數據庫類型
                        varchar(長度) 字符串
                        int 整形
                        <property name="birthday">
                            <column name="birthday" sql-type="datetime"></column>
                        </property>
                        javabean 一般使用類型 java.util.Date
                        jdbc規範提供3中
                            java類型              mysql類型
                            java.sql.Date       date
                            java.sql.time       time
                            java.sql.timestamp  timestamp
                            null                datetime

                            以上三個類型都是java.util.Date子類

                length : 列的長度。默認值:255
                not-null : 是否爲null
                unique : 是否唯一
                access:設置映射使用PO類屬性或字段
                    property : 使用PO類屬性,必須提供setter、getter方法
                    field : 使用PO類字段,一般很少使用。
                insert 生成insert語句時,是否使用當前字段。
                update 生成update語句時,是否使用當前字段。
                    默認情況:hibernate生成insert或update語句,使用配置文件所有項
        注意:配置文件如果使用關鍵字,列名必須使用重音符    

主鍵

<id>配置主鍵
                name:屬性名稱
                access="" 設置使用屬性還是字段
                column=""  表的列名
                length=""  長度
                type="" 類型
            <generator> class屬性用於設置主鍵生成策略
                1.increment 由hibernate自己維護自動增長
                    底層通過先查詢max值,再+1策略
                    不建議使用,存在線程併發問題
                2.identity hibernate底層採用數據庫本身自動增長列
                    例如:mysql auto_increment
                3.sequence hibernate底層採用數據庫序列
                    例如:oracle 提供序列
                4.hilo 

                    </generator>
                5.native 根據底層數據庫的能力選擇 identity、sequence 或者 hilo 中的一個。【】
                ##以上策略使用整形,long, short 或者 int 類型
                6.uuid 採用字符串唯一值【】
                ##以上策略 代理主鍵,有hibernate維護。
                7.assigned 自然主鍵,由程序自己維護。【】
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章