1. 程式人生 > >Hibernate基礎學習2

Hibernate基礎學習2

per session -- 相關 綁定 transacti cst nts pre

Hibernate基礎學習2

0)測試hibernate的一級緩存,事務以及查詢語句

技術分享圖片

1)Hibernate的一些相關概念

技術分享圖片
hibernate的一級緩存
1)緩存是為了提高該框架對數據庫的查詢速度
2)一級緩存是將獲取的結果放到了session中,再次查詢直接從緩存中獲取(提高查詢效率)
3)緩存進階之快照:將獲取的一份結果放到session中,一份放到快照中,當修改時,對比快照與緩存,
如果數據沒有發生變化,直接結束修改(避免不必要的修改)

hibernate的事務
在業務開始之前打開事務,在業務結束時提交事務,如果出現異常則回滾事務

1)事務的4大特性
A:原子性(Atomicity)
       事務是數據庫的邏輯工作單位,事務中包括的諸操作要麽全做,要麽全不做。
B:一致性(Consistency)
       事務執行的結果必須是使數據庫從一個一致性狀態變到另一個一致性狀態。一致性與原子性是密切相關的。
C:隔離性(Isolation)
      一個事務的執行不能被其他事務幹擾。
D:持續性
/永久性(Durability) 一個事務一旦提交,它對數據庫中數據的改變就應該是永久性的。 2)事務並發存在的問題 1.丟失更新:撤消一個事務時,把其它事務已提交的更新的數據覆蓋了。 2.臟讀:一個事務讀到另一個事務未提交的更新數據。 3.幻讀:一個事務執行兩次查詢,但第二次查詢比第一次查詢多出了一些數據行。 4.不可重復讀:一個事務兩次讀同一行數據,可是這兩次讀到的數據不一樣。 3)事務的隔離級別(處理事務並發問題) 1.Read uncommitted(讀未提交) 顧名思義,就是一個事務可以讀取另一個未提交事務的數據。 事例:老板要給程序員發工資,程序員的工資是3.6萬
/月。但是發工資時老板不小心按錯了數字, 按成3.9萬/月,該錢已經打到程序員的戶口,但是事務還沒有提交,就在這時,程序員去查看自己這個月的工資, 發現比往常多了3千元,以為漲工資了非常高興。但是老板及時發現了不對,馬上回滾差點就提交了的事務, 將數字改成3.6萬再提交。 分析:實際程序員這個月的工資還是3.6萬,但是程序員看到的是3.9萬。他看到的是老板還沒提交事務時的數據。這就是臟讀。 那怎麽解決臟讀呢?Read committed!讀提交,能解決臟讀問題。 2.Read committed(讀提交) 顧名思義,就是一個事務要等另一個事務提交後才能讀取數據。 事例:程序員拿著信用卡去享受生活(卡裏當然是只有3.6萬),當他埋單時(程序員事務開啟), 收費系統事先檢測到他的卡裏有3.6萬,就在這個時候!!程序員的妻子要把錢全部轉出充當家用,並提交。 當收費系統準備扣款時,再檢測卡裏的金額,發現已經沒錢了(第二次檢測金額當然要等待妻子轉出金額事務提交完)。 程序員就會很郁悶,明明卡裏是有錢的… 分析:這就是讀提交,若有事務對數據進行更新(UPDATE)操作時,讀操作事務要等待這個更新操作事務提交後 才能讀取數據,可以解決臟讀問題。但在這個事例中,出現了一個事務範圍內兩個相同的查詢卻返回了不同數據, 這就是不可重復讀。 那怎麽解決可能的不可重復讀問題?Repeatable read !
3.Repeatable read(重復讀) 就是在開始讀取數據(事務開啟)時,不再允許修改操作 事例:程序員拿著信用卡去享受生活(卡裏當然是只有3.6萬),當他埋單時(事務開啟,不允許其他事務的UPDATE修改操作), 收費系統事先檢測到他的卡裏有3.6萬。這個時候他的妻子不能轉出金額了。接下來收費系統就可以扣款了。 分析:重復讀可以解決不可重復讀問題。寫到這裏,應該明白的一點就是,不可重復讀對應的是修改,即UPDATE操作。 但是可能還會有幻讀問題。因為幻讀問題對應的是插入INSERT操作,而不是UPDATE操作。 什麽時候會出現幻讀? 事例:程序員某一天去消費,花了2千元,然後他的妻子去查看他今天的消費記錄(全表掃描FTS,妻子事務開啟), 看到確實是花了2千元,就在這個時候,程序員花了1萬買了一部電腦,即新增INSERT了一條消費記錄,並提交。 當妻子打印程序員的消費記錄清單時(妻子事務提交),發現花了1.2萬元,似乎出現了幻覺,這就是幻讀。 那怎麽解決幻讀問題?Serializable! 4.Serializable(序列化,串行化:排隊執行) Serializable 是最高的事務隔離級別,在該級別下,事務串行化順序執行,可以避免臟讀、不可重復讀與幻讀。 但是這種事務隔離級別效率低下,比較耗數據庫性能,一般不使用。
study

2)在主配置文件中添加如下配置對事務進行管理

<!-- 指定hibernate操作數據庫時的隔離級別
            #hibernate.connection.isolation 1|2|4|8
            0001    1    讀未提交
            0010    2    讀已提交
            0100    4    可重復讀
            1000    8    串行化
         -->
        <property name="hibernate.connection.isolation">4</property>
        <!-- 指定session與當前線程綁定,事務中確保使用同一個session -->
        <property name="hibernate.current_session_context_class">thread</property>

3)測試對象的3種狀態

技術分享圖片
package com.hibernate.test;

import com.hibernate.domain.Customer;
import com.hibernate.utils.HibernateUtils;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;

/**
 * @author: 肖德子裕
 * @date: 2018/11/15 11:41
 * @description: 測試hibernate框架
 */
public class Test {
    /**
     * 添加客戶信息
     */
    @org.junit.Test
    public void addTest(){
        //創建Session對象
        Session session = HibernateUtils.openSession();
        //開啟事務並獲取事務對象
        Transaction tx = session.beginTransaction();

        /********************* 數據庫操作 **********************/

        //對象的3種狀態體現(狀態之間的轉換)
        //瞬時狀態:沒有ID,沒有與session關聯
        Customer customer=new Customer();
        customer.setCust_name("xdzy");
        //持久化狀態:有ID,與session有關聯
        session.save(customer);

        /*******************************************************/

        tx.commit();
        //遊離|托管狀態,有ID,與sesssion無關聯
        session.close();
    }

    /**
     * 刪除客戶信息
     */
    @org.junit.Test
    public void deleteTest(){
        //創建Session對象
        Session session = HibernateUtils.openSession();
        //開啟事務並獲取事務對象
        Transaction tx = session.beginTransaction();

        /********************* 數據庫操作 **********************/

        //獲取ID為1的客戶
        Customer customer = session.get(Customer.class, 30L);
        //刪除
        session.delete(customer);

        /*******************************************************/

        tx.commit();
        session.close();
    }

    /**
     * 修改客戶信息
     */
    @org.junit.Test
    public void updateTest(){
        //創建Session對象
        Session session = HibernateUtils.openSession();
        //開啟事務並獲取事務對象
        Transaction tx = session.beginTransaction();

        /********************* 數據庫操作 **********************/

        Customer customer = session.get(Customer.class, 6L);
        customer.setCust_name("xdzy");
        session.update(customer);

        /*******************************************************/

        tx.commit();
        session.close();
    }

    /**
     * 查詢客戶信息
     */
    @org.junit.Test
    public void selectTest(){
        //創建Session對象
        Session session = HibernateUtils.openSession();
        //開啟事務並獲取事務對象
        Transaction tx = session.beginTransaction();

        /********************* 數據庫操作 **********************/

        Customer customer = session.get(Customer.class, 6L);
        System.out.println(customer);

        /*******************************************************/

        tx.commit();
        session.close();
    }
}
測試

4)測試事務中獲取session的方法

技術分享圖片
package com.hibernate.test;

import com.hibernate.utils.HibernateUtils;
import org.hibernate.Session;
import org.junit.Test;

/**
 * @author: 肖德子裕
 * @date: 2018/11/16 10:00
 * @description: 測試事務中獲取session的方法
 */
public class Test2 {
    /**
     * 獲取綁定的session是同一個,可以確保事務使用同一個session
     * 用該方法獲取事務提交後會自動關閉,所以事務提交之後不能手動關閉,會引發異常
     */
    @Test
    public void test(){
        Session session = HibernateUtils.getCurrentSession();
        Session session1 = HibernateUtils.getCurrentSession();
        System.out.println(session==session1);
    }

    /**
     * 獲取新的session
     */
    @Test
    public void test1(){
        Session session = HibernateUtils.openSession();
        Session session1 = HibernateUtils.openSession();
        System.out.println(session==session1);
    }
}
測試

5)測試HQL語句

技術分享圖片
package com.hibernate.test;

import com.hibernate.domain.Customer;
import com.hibernate.utils.HibernateUtils;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;

import java.util.List;

/**
 * @author: 肖德子裕
 * @date: 2018/11/16 10:26
 * @description: 測試HQL語句(hibernate獨有的面向對象的語法)(適合不復雜的多表查詢)
 * HQL語句不能出現數據庫相關字段,而是類的屬性或類的名稱
 */
public class Test3 {
    /**
     * 查詢所有
     */
    @Test
    public void test(){
        //創建Session對象
        Session session = HibernateUtils.openSession();
        //開啟事務並獲取事務對象
        Transaction tx = session.beginTransaction();

        /********************* 數據庫操作 **********************/

        //1)書寫HQL語句
        String hql="from Customer";
        //2)創建查詢對象
        Query query = session.createQuery(hql);
        //3)執行查詢
        List<Customer> list = query.list();

        System.out.println(list);

        /*******************************************************/

        tx.commit();
        session.close();
    }

    /**
     * 指定查詢
     */
    @Test
    public void test1(){
        //創建Session對象
        Session session = HibernateUtils.openSession();
        //開啟事務並獲取事務對象
        Transaction tx = session.beginTransaction();

        /********************* 數據庫操作 **********************/

        //1)書寫HQL語句
        String hql="from Customer where cust_id=6";
        //2)創建查詢對象
        Query query = session.createQuery(hql);
        //3)執行查詢
        Customer customer = (Customer) query.uniqueResult();

        System.out.println(customer);

        /*******************************************************/

        tx.commit();
        session.close();
    }

    /**
     * 占位符
     */
    @Test
    public void test2(){
        //創建Session對象
        Session session = HibernateUtils.openSession();
        //開啟事務並獲取事務對象
        Transaction tx = session.beginTransaction();

        /********************* 數據庫操作 **********************/

        //1)書寫HQL語句
        String hql="from Customer where cust_id=?";
        //2)創建查詢對象
        Query query = session.createQuery(hql);
        //3)設置參數
        //query.setLong(0,6L);
        query.setParameter(0,6L);
        //4)執行查詢
        Customer customer = (Customer) query.uniqueResult();

        System.out.println(customer);

        /*******************************************************/

        tx.commit();
        session.close();
    }

    /**
     * 命名占位符
     */
    @Test
    public void test3(){
        //創建Session對象
        Session session = HibernateUtils.openSession();
        //開啟事務並獲取事務對象
        Transaction tx = session.beginTransaction();

        /********************* 數據庫操作 **********************/

        //1)書寫HQL語句
        String hql="from Customer where cust_id= :cust_id";
        //2)創建查詢對象
        Query query = session.createQuery(hql);
        //3)設置參數
        //query.setLong(0,6L);
        query.setParameter("cust_id",6L);
        //4)執行查詢
        Customer customer = (Customer) query.uniqueResult();

        System.out.println(customer);

        /*******************************************************/

        tx.commit();
        session.close();
    }

    /**
     * 分頁查詢所有
     */
    @Test
    public void test4(){
        //創建Session對象
        Session session = HibernateUtils.openSession();
        //開啟事務並獲取事務對象
        Transaction tx = session.beginTransaction();

        /********************* 數據庫操作 **********************/

        //1)書寫HQL語句
        String hql="from Customer";
        //2)創建查詢對象
        Query query = session.createQuery(hql);
        //3)設置分頁條件(從0開始查詢1條)
        query.setFirstResult(0);
        query.setMaxResults(1);
        //4)執行查詢
        List<Customer> list = query.list();

        System.out.println(list);

        /*******************************************************/

        tx.commit();
        session.close();
    }
}
測試

6)測試Criteria語句

技術分享圖片
package com.hibernate.test;

import com.hibernate.domain.Customer;
import com.hibernate.utils.HibernateUtils;
import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.criterion.Projection;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.junit.Test;

import java.util.List;

/**
 * @author: 肖德子裕
 * @date: 2018/11/16 10:26
 * @description: 測試criteria語句(hibernate獨有的無語句的全面向對象的查詢語法)(適合單表查詢)
 * > (gt)
 * >= (ge)
 * < (lt)
 * <= (le)
 * == (eq)
 * != (ne)
 * in (in)
 * between and (between)
 * like (like)
 * is not null (isNotNull)
 * is null (isNull)
 * or (or)
 * and (and)
 */
public class Test4 {
    /**
     * 查詢所有
     */
    @Test
    public void test(){
        //創建Session對象
        Session session = HibernateUtils.openSession();
        //開啟事務並獲取事務對象
        Transaction tx = session.beginTransaction();

        /********************* 數據庫操作 **********************/

        Criteria criteria = session.createCriteria(Customer.class);
        List list = criteria.list();
        System.out.println(list);

        /*******************************************************/

        tx.commit();
        session.close();
    }

    /**
     * 指定查詢
     */
    @Test
    public void test1(){
        //創建Session對象
        Session session = HibernateUtils.openSession();
        //開啟事務並獲取事務對象
        Transaction tx = session.beginTransaction();

        /********************* 數據庫操作 **********************/

        Criteria criteria = session.createCriteria(Customer.class);
        criteria.add(Restrictions.eq("cust_id",6L));
        Customer customer = (Customer) criteria.uniqueResult();
        System.out.println(customer);

        /*******************************************************/

        tx.commit();
        session.close();
    }

    /**
     * 分頁查詢所有
     */
    @Test
    public void test2(){
        //創建Session對象
        Session session = HibernateUtils.openSession();
        //開啟事務並獲取事務對象
        Transaction tx = session.beginTransaction();

        /********************* 數據庫操作 **********************/

        Criteria criteria = session.createCriteria(Customer.class);
        criteria.setFirstResult(0);
        criteria.setMaxResults(1);
        List list = criteria.list();
        System.out.println(list);

        /*******************************************************/

        tx.commit();
        session.close();
    }

    /**
     * 查詢總記錄數,分頁總行數
     */
    @Test
    public void test3(){
        //創建Session對象
        Session session = HibernateUtils.openSession();
        //開啟事務並獲取事務對象
        Transaction tx = session.beginTransaction();

        /********************* 數據庫操作 **********************/

        Criteria criteria = session.createCriteria(Customer.class);
        criteria.setProjection(Projections.rowCount());
        Long count = (Long) criteria.uniqueResult();
        System.out.println(count);

        /*******************************************************/

        tx.commit();
        session.close();
    }
}
測試

7)測試原生SQL語句

技術分享圖片
package com.hibernate.test;

import com.hibernate.domain.Customer;
import com.hibernate.utils.HibernateUtils;
import org.hibernate.*;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.junit.Test;

import java.lang.reflect.Array;
import java.util.Arrays;
import java.util.List;

/**
 * @author: 肖德子裕
 * @date: 2018/11/16 10:26
 * @description: 測試原生SQL語句查詢(適合復雜多表查詢)
 */
public class Test5 {
    /**
     * 查詢所有
     */
    @Test
    public void test(){
        //創建Session對象
        Session session = HibernateUtils.openSession();
        //開啟事務並獲取事務對象
        Transaction tx = session.beginTransaction();

        /********************* 數據庫操作 **********************/

        String sql="select * from cst_customer";
        SQLQuery query = session.createSQLQuery(sql);
        List<Object[]> list = query.list();
        for (Object[] customers:list){
            System.out.println(Arrays.toString(customers));
        }

        /*******************************************************/

        tx.commit();
        session.close();
    }

    /**
     * 查詢所有並且封裝到對象
     */
    @Test
    public void test1(){
        //創建Session對象
        Session session = HibernateUtils.openSession();
        //開啟事務並獲取事務對象
        Transaction tx = session.beginTransaction();

        /********************* 數據庫操作 **********************/

        String sql="select * from cst_customer";
        SQLQuery query = session.createSQLQuery(sql);
        query.addEntity(Customer.class);
        List<Customer> list = query.list();
        System.out.println(list);

        /*******************************************************/

        tx.commit();
        session.close();
    }

    /**
     * 占位符
     */
    @Test
    public void test2(){
        //創建Session對象
        Session session = HibernateUtils.openSession();
        //開啟事務並獲取事務對象
        Transaction tx = session.beginTransaction();

        /********************* 數據庫操作 **********************/

        String sql="select * from cst_customer where cust_id=?";
        SQLQuery query = session.createSQLQuery(sql);
        query.setParameter(0,6L);
        query.addEntity(Customer.class);
        Customer customer = (Customer) query.uniqueResult();
        System.out.println(customer);

        /*******************************************************/

        tx.commit();
        session.close();
    }

    /**
     * 分頁查詢
     */
    @Test
    public void test3(){
        //創建Session對象
        Session session = HibernateUtils.openSession();
        //開啟事務並獲取事務對象
        Transaction tx = session.beginTransaction();

        /********************* 數據庫操作 **********************/

        String sql="select * from cst_customer limit ?,?";
        SQLQuery query = session.createSQLQuery(sql);
        query.setParameter(0,0);
        query.setParameter(1,1);
        query.addEntity(Customer.class);
        List<Customer> list = query.list();
        System.out.println(list);

        /*******************************************************/

        tx.commit();
        session.close();
    }
}
測試

Hibernate基礎學習2