Hibernate 特性 操做各類語法 火推05

Hibernate

是一款開源的ORM框架,hibernate是在咱們的MVC設計模式中,充當的是持久化層,負責數據的操做交互。java

Jbossmysql

2001-2004算法

搭建步驟:sql

1:導包

    <!-- hibernate -->
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-core</artifactId>
        <version>4.2.21.Final</version>
    </dependency>

2:加載hibernate配置文件

    hibernate.cfg.xml
    note.hbm.xml

hibernate.cfg.xml:數據庫

<?xml version='1.0' encoding='UTF-8'?>
<!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="dialect">
            org.hibernate.dialect.MySQLDialect
        </property>

        <!-- 數據庫鏈接信息 -->
        <property name="connection.url">
            jdbc:mysql://localhost:3306/test?useUnicode=true&amp;characterEncoding=utf8
        </property>
        <property name="connection.username">root</property>
        <property name="connection.password">123456</property>
        <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
        <!-- 顯示底層sql語句 -->
        <property name="show_sql">true</property>
        <property name="format_sql">true</property>

        <mapping resource="hbm/Note.hbm.xml" />

    </session-factory>
</hibernate-configuration>

note.hbm.xml:設計模式

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>

    <!-- name:表明數據庫表所對應的java實體對象信息
         table:表明的是數據庫表名稱
     -->
     <class name="com.xdl.entity.Note" table="note">

        <!-- 必需要指定主鍵ID -->
        <id name="id" type="integer" column="id"></id>

        <!-- 其它字段使用property屬性標籤訂義,其中:
            name:表明數據庫表中的字段所對應的實體對象中的屬性名稱
            type:表明數據庫表中的字段類型,注意:首字母必須小寫
            column:表明數據庫表中的字段名稱
         -->
        <property name="context" type="string" column="context"></property>
        <property name="publishTime" type="date" column="publishTime"></property>
        <property name="likeCount"  type="integer" column="likeCount"></property>
        <property name="userId"  type="integer" column="userId"></property>
     </class>

</hibernate-mapping>

演變:api

jdbc--->jdbTemplate--->mybatis---->hibernate

hibernate與mybatis的區別?緩存

1:hibernate學習難度大於mybatis
2:hibernate的擴展性和移植性要比mybatis強
3:hibernate支持count、sum、avg函數,可是不支持一些類型轉換,好比:日期轉換,字符轉換等
4:hibernate支持事務,而且自支持緩存,如:一級緩存、二級緩存和查詢緩存,可使用第三方緩存技術
5:hibernate不建議使用left join,而mybatis能夠支持
6:hibernate自支持分頁條件,而mybatis須要配置分頁插件
7:hibernate通常應用與老系統的維護和開發,目前流行的企業解決方案爲mybatis
8:hibernate不須要寫sql語句,是自動生成的,而mybatis須要寫sql語句

數據庫工具類

/**
 * 數據庫工具類,獲取數據庫鏈接session
 * @author likang
 * @date   2018-1-11 上午9:58:18
 */
public class HibernateUtils {

    public static Session getSession(){
        Configuration conf = new Configuration();
        conf.configure("hibernate.cfg.xml");
        SessionFactory sessionFactory = conf.buildSessionFactory();
        Session session = sessionFactory.openSession();
        return session;
    }
}

增刪改查操做

問題:(session.close())性能優化

1:數據庫遊標越界
2:too many connect

解決方式:session

1:重啓數據庫----命令重啓---service mysqld stop/start/restart
2:使用命令查詢當前鏈接數據庫的進程號,直接kill
3:常常在開發環境使用--藉助鏈接數據庫的客戶端

TestHibernate.java:

/**
 * 測試hibernate框架操做
 * @author likang
 * @date   2018-1-11 上午10:24:19
 */
public class TestHibernate {


    /**
     * 查詢操做
     */
    @Test
    public void test1(){
        Session session = HibernateUtils.getSession();
//Note.hbm.xml中指定的表,查詢數據庫中note表id爲16條的信息,自動生成sql語句,不須要手寫sql語句
        Note note = (Note) session.get(Note.class, 16);
        if (note != null) {
            System.out.println(note.getContext());
        }else{
            System.out.println("查詢數據爲空");
        }
    }

    /**
     * 增長操做
     *  寫操做:須要開啓事務,執行完畢以後,須要關閉
     */
    @Test
    public void test2(){
        Session session = HibernateUtils.getSession();
        Note note = new Note();
        note.setId(201);
        note.setContext("java13測試數據2");
        note.setLikeCount(100);
        note.setUserId(1);
        note.setPublishTime(new Date(System.currentTimeMillis()));
        Transaction ts = session.beginTransaction();//開啓事務
        session.save(note);
        ts.commit();//提交----flush---commit
        session.close();
    }

    /**
     * 刪除操做
     *      後臺實際執行了兩步sql
     *      1:先執行查詢操做,若是數據存在,則繼續執行delete語句,若是不存在,則不執行刪除語句
     */
    @Test
    public void test3(){
        Session session = HibernateUtils.getSession();
        Note note = new Note();
        note.setId(200);
        Transaction ts = session.beginTransaction();//開啓事務
        session.delete(note);
        ts.commit();//提交----flush---commit
        session.close();
    }


    /**
     * 修改操做
     *      在修改數據以前,通常是先進行查詢,將數據結果集,賦值給note
     * 
     */
    @Test
    public void test4(){

        Session session = HibernateUtils.getSession();

        Note note = (Note) session.get(Note.class, 201);
//      Note note = new Note();
//      note.setId(201);
        note.setLikeCount(300);

        Transaction ts = session.beginTransaction();//開啓事務
        session.update(note);
        ts.commit();//提交----flush---commit
        session.close();

    }
}

Hibernate主鍵管理

1.sequence 序列

通常適用於oracle數據庫

2.identity 主鍵自增

通常用於mysql、SqlServer數據庫

3.native 自動匹配

能夠自動匹配當前數據庫類型,
若是當前數據庫是mysql,則自動將主鍵設置爲identity,
若是當前數據庫爲oracle,則自動將主鍵識別爲sequence

4.increment 自動獲取主鍵+1

自動的去數據庫獲取最大值的ID,而後+1,設置爲主鍵ID

5.uuid/hilo 隨機算法和高低位算法

32---varchar(32)

6.assigned

須要咱們自動的去設置主鍵ID,須要添加setId();

配置主鍵的位置:

note.hbm.xml中:

    <id name="id" type="integer" column="id">
        <!-- 指定表的主鍵策略 -->
        <generator class="identity"></generator>
    </id>

Hibernate查詢操做

HQL查詢

HQL:hibernate query Language(面向對象的查詢)----對象化  (實體)

select * from Note(實體類名)

SQL:Structured Query Language(面向結構的查詢)---結構化 (數據庫表和表字段)

select * from note(數據庫表名)

HQL與SQL有什麼區別?

1:HQL是面向對象的查詢,SQL是面向結構的查詢
2:HQL對查詢語句的大小寫很是敏感,而SQL對查詢語句的大小寫字段屬性依賴於咱們的數據庫配置信息
3:HQL在進行查詢的時候,使用的是類名和屬性名稱,而SQL在查詢的時候,使用的是數據庫表名和字段名
4:若是咱們是須要查詢表中全部的數據,那麼HQL,能夠省略select *,直接使用 from Note,SQL則不能省略
5:HQL不支持類型轉換,如:日期轉換、字符轉換等,SQL支持
6:HQL不能進行特別複雜的查詢操做,也就是說,不建議使用left join,而SQL,能夠無限制的使用left join等關聯,進行復雜查詢

示例:

public class TestHQL {

    /**
     * 查詢操做
     */
    @Test
    public void test1(){
        Session session = HibernateUtils.getSession();
        String hql = "from Note";//‘Note’表明類名,若是查詢所有,則能夠省略select *
        Query query = session.createQuery(hql); //返回的是Query對象
        List<Note> list = query.list();
        if (list != null && list.size() > 0) {
            for (int i = 0; i < list.size(); i++) {
                System.out.println("筆記內容爲:"+list.get(i).getContext()+"--------時間爲:"+list.get(i).getPublishTime());
            }
        }
    }

    /**
     * 帶有where條件的查詢
     */
    @Test
    public void test2(){
        Session session = HibernateUtils.getSession();
        String hql = "from Note where publishTime >?";
        Query query = session.createQuery(hql);
        query.setDate(0, Date.valueOf("2017-12-01"));//第一個參數表明hql中參數的下標,從0開始,第二個參數爲賦值

        List<Note> list = query.list();
        if (list != null && list.size() > 0) {
            for (int i = 0; i < list.size(); i++) {
                System.out.println("id:"+list.get(i).getId()+"筆記內容爲:"+list.get(i).getContext()+"--------時間爲:"+list.get(i).getPublishTime());
            }
        }
    }

    /**
     * 分頁查詢
     */
    @Test
    public void test3(){

        Session session = HibernateUtils.getSession();
        String hql = "from Note";//‘Note’表明類名,若是查詢所有,則能夠省略select *
        Query query = session.createQuery(hql);
        query.setFirstResult(6);//表明的是從數據庫第幾條數據開始,不包含當前條數
        query.setMaxResults(2);//一共獲取多少條

        List<Note> list = query.list();
        if (list != null && list.size() > 0) {
            for (int i = 0; i < list.size(); i++) {
                System.out.println("id:"+list.get(i).getId()+"筆記內容爲:"+list.get(i).getContext()+"--------時間爲:"+list.get(i).getPublishTime());
            }
        }
    }

    /**
     * 查詢個數
     */
    @Test
    public void test4(){
        Session session = HibernateUtils.getSession();
        String hql = "select count(*) from Note";
        Query query = session.createQuery(hql);

        Long count = (Long) query.uniqueResult();
        System.out.println("一共有:"+count);

    }
}

Criteria查詢

複雜條件查詢:

示例:

public class TestCriteria {


    /**
     * 查詢操做
     */
    @Test
    public void test1(){

        Session session = HibernateUtils.getSession();
        Criteria criteria = session.createCriteria(Note.class);//直接實體對象映射就能夠查詢note表
        List<Note> list = criteria.list();
        if (list != null && list.size() > 0) {
            for (int i = 0; i < list.size(); i++) {
                System.out.println("內容爲:"+list.get(i).getContext());
            }
        }
    }

    /**
     * 1:select * from note where note.publishTime > '2017-12-01'
     */
    @Test
    public void test2(){

        Session session = HibernateUtils.getSession();
        Criteria criteria = session.createCriteria(Note.class);
        //select * from note where note.publishTime > '2017-12-01'
//      criteria.add(Restrictions.gt("publishTime", Date.valueOf("2017-12-01")));//publishTime > '2017-12-01'

        //select * from note where note.publishTime > '2017-12-01' and userId = 1
//      criteria.add(Restrictions.eq("userId", 1));// 時間publishTime 和userId拼接成一個sql語句了

        ////select * from note where note.publishTime > '2017-12-01' or userId = 1
        criteria.add(Restrictions.or(Restrictions.gt("publishTime", Date.valueOf("2017-12-01")),
                Restrictions.eq("userId", 1)));

        criteria.addOrder(Order.desc("publishTime"));//倒序
                                                     //Order.asc("publishTime");正序
        List<Note> list = criteria.list();

        if (list != null && list.size() > 0) {
            for (int i = 0; i < list.size(); i++) {
                System.out.println("時間爲:"+list.get(i).getPublishTime()+"--------"+"內容爲:"+list.get(i).getContext());
            }
        }

    }
}

NativeSQL查詢

原生sql查詢:

/**
 * 原生sql查詢
 * @author likang
 * @date   2018-1-11 下午2:41:15
 */
public class TestNativeSQL {

    @Test
    public void test1(){
        Session session = HibernateUtils.getSession();
        String sql = "select * from note";//note 是數據庫表名
        SQLQuery query = session.createSQLQuery(sql);
        /*List<Note> list = query.list();
        if (list != null && list.size() > 0) {
            for (int i = 0; i < list.size(); i++) {
                System.out.println(list.get(i).getContext());
            }
        }*/ //會提示類型轉換異常,

        List<Object[]> list = query.list();
        if (list != null && list.size() > 0) {
            for (Object[] obj : list) {
                System.out.println(obj[1]);
            }
        }
    }


    /**
     * 推薦使用的查詢方式
     */
    @Test
    public void test2(){
        Session session = HibernateUtils.getSession();
        String sql = "select * from note";//note 是數據庫表名
        SQLQuery query = session.createSQLQuery(sql);
        query.addEntity(Note.class);//加載數據庫表映射文件信息
        List<Note> list = query.list();
        if (list != null && list.size() > 0) {
            for (int i = 0; i < list.size(); i++) {
                System.out.println(list.get(i).getContext());
            }
        }

    }
}

Hibernate註解應用

類名:

@Entity//指定當前實體爲一個映射關係
@Table(name="note")//映射到數據庫note表

屬性字段名:

主鍵:
@Id//指定實體對象主鍵
@Column(name="id")//指定對應到數據庫表中的字段名稱
@GeneratedValue(strategy=GenerationType.IDENTITY)//設置主鍵的生成策略

其它字段:
@Column(name="context")

須要將hibernate.cfg.xml中的加載映射文件修改成:

<mapping class="com.xdl.entity.Note"/>

Hibernate特性

延遲加載

hibernate中有一些特定的api具備延遲加載的特性,在使用了具備延遲加載特性的api以後,不會馬上去開啓事務並指定hql語句,直到使用對象的時候,纔會去調用事務,執行查詢。

load:具備延遲加載特性
find:具備延遲加載的特性
iterate:具備延遲加載的特性

get:沒有延遲加載特性
list:沒延遲加載的特性

問題:(使用了延遲加載的特性API)

org.hibernate.LazyInitializationException: could not initialize proxy ...no session

解決:

明天講(opensessionviewFilter)

示例:

@Test
public void test1(){
    Session session = HibernateUtils.getSession();

//  Note note2 = (Note) session.get(Note.class, 16);

    Note note1 = (Note) session.load(Note.class, 16);

}

緩存(性能優化)

  • 一級緩存

    hibernate默認開啓一級緩存,而且不須要作任何的配置
    
    session獨享

示例:

@Test
public void test1(){
//Session獨享 打印第一條sql語句,後面的直接獲得數據
    Session session = HibernateUtils.getSession();

    Note note = (Note) session.get(Note.class, 16);
    System.out.println(note.getContext());

//  Session session1 = HibernateUtils.getSession();
//  
//  Note note1 = (Note) session1.get(Note.class, 16);
//  System.out.println(note1.getContext());

}
  • 二級緩存
  • 查詢緩存

 

持久化(session)

hibernate 數據狀態

狀態值:

transient:臨時狀態

    Note note = new Note();
    此狀態的數據,能夠隨時被GC //GC垃圾回收機制回收

persistent:持久化狀態

    session.save(note);---將臨時狀態數據--->持久化狀態數據
    session.delete(note);--->將持久化狀態數據-->臨時狀態數據--->刪除

    持久化狀態的數據,永遠不會自動gc的

detached:遊離狀態/託管狀態

    session.close();---將持久---》託管
    session.update();---將託管---》持久

    遊離狀態能夠隨時被GC
相關文章
相關標籤/搜索