二、加深理解Hibernate框架

Hibernate_緩存&事務(wù)&批量查詢概述

一、 Hibernate的持久化類

持久化類是指一個(gè)Java類和數(shù)據(jù)庫建立了映射關(guān)系掰吕,那么這個(gè)類就是持久化類。

1. 持久化類的編寫規(guī)則:

  • 持久化類需要有無參的構(gòu)造方法颅痊。
    • 因?yàn)镠ibernate的底層需要使用反射生成類的實(shí)例殖熟。
  • 持久化類的屬性需要私有,私有的屬性需要提供set和get方法。
    • 因?yàn)镠ibernate底層要將查詢到的數(shù)據(jù)進(jìn)行封裝斑响。
  • 持久化類盡量使用包裝類的類型菱属。
    • 因?yàn)榘b類與普通類的默認(rèn)值不同钳榨。例:Integer為null,int為0.在數(shù)據(jù)庫表中代表的含義包裝類更準(zhǔn)確。
  • 持久化類需要有一個(gè)唯一標(biāo)識(shí)OID與表的主鍵對應(yīng)纽门。
    • Hibernate不允許在內(nèi)存中出現(xiàn)兩個(gè)相同OID的持久化對象薛耻。
  • 持久化類不能使用final修飾。
    • 因?yàn)镠ibernate中有延遲加載機(jī)制,這個(gè)機(jī)制會(huì)產(chǎn)生代理對象膜毁。而這個(gè)代理對象是使用字節(jié)碼的增強(qiáng)技術(shù)完成的昭卓,其實(shí)就是產(chǎn)生了一個(gè)當(dāng)前類的子類對象實(shí)現(xiàn)的。

2. Hibernate的主鍵生成策略

  • 自然主鍵
    • 把具有業(yè)務(wù)含義的字段作為主鍵瘟滨。
  • 代理主鍵
    • 把不具備業(yè)務(wù)含義的字段作為主鍵,與對象本身無關(guān),該字段一般取名"ID".
img08.png

我們在映射文件中設(shè)置選擇native,根據(jù)數(shù)據(jù)庫底層的支持來自動(dòng)生成策略能颁。

3. 持久化對象的三種狀態(tài)

  • 瞬時(shí)態(tài)
    • 沒有OID杂瘸,與Hibernate的Session沒有任何關(guān)聯(lián)
  • 持久態(tài)
    • 有OID,與Session有關(guān)聯(lián)
  • 托管態(tài)
    • 有OID伙菊,與Session沒有關(guān)聯(lián)

瞬時(shí)態(tài):

對象創(chuàng)建時(shí),就是瞬時(shí)態(tài)败玉。
如: User user = new User();
    user.serUname("悟空");
    user.setUpassword("123");
這里面的user都是瞬時(shí)態(tài),沒有OID,與Session沒有關(guān)聯(lián)镜硕。

持久態(tài):

session.save(user);
這里的user與session產(chǎn)生關(guān)聯(lián)运翼,加入到了Session的緩存中,生成了持久化標(biāo)識(shí)OID,是持久態(tài)

此外,get/load/find...等方法獲取的對象也是持久態(tài)對象

托管態(tài):

session.close();
System.out.println(user);
這里的user有了OID,但是與Session沒有了關(guān)聯(lián),是托管態(tài)

持久化對象的三種對象之間的互相轉(zhuǎn)換:

img09.png

上圖:

1. 一個(gè)對象被new出來之后處于瞬時(shí)態(tài)兴枯;當(dāng)對瞬時(shí)態(tài)對象執(zhí)行Session對象的save()/saveOrUpdate()方法后血淌,
該對象會(huì)被放入Session的一級(jí)緩存,進(jìn)入持久態(tài);當(dāng)對持久態(tài)對象執(zhí)行evict()/close()/clear()操作后,
對象進(jìn)入托管態(tài)财剖。

2. Session對象直接執(zhí)行g(shù)et()/load()/find()/iterate()等方法從數(shù)據(jù)庫查詢對象時(shí),查詢到的對象也屬于
持久態(tài)悠夯;

3. 當(dāng)對托管態(tài)對象執(zhí)行Session的upadte()/saveOrUpadate()方法時(shí),會(huì)轉(zhuǎn)為持久態(tài);瞬時(shí)態(tài)與托管態(tài)的對象
不在Session對象的管理范圍內(nèi)躺坟,因此一段時(shí)間后會(huì)被JVM回收沦补。

持久化對象的特點(diǎn):能夠自動(dòng)更新數(shù)據(jù)庫

持久化對象能夠自動(dòng)更新數(shù)據(jù)庫依賴于Hibernate的一級(jí)緩存。

@Test
//Hibernate持久化對象自動(dòng)更新數(shù)據(jù)庫
public void test() {
    //1. 獲取Hibernate配置對象加載配置
    //2. 獲取SessionFactory對象
    //3. 獲取Session對象
    Session session = HibernateUtils.openSession();
    //4. 開啟事務(wù)
    Transaction transaction = session.beginTransaction();
    //5. 執(zhí)行業(yè)務(wù)邏輯
    User user = session.get(User.class, 2);//獲得持久化對象
    user.setUname("外星人");

    //無需手動(dòng)調(diào)用session.save(user);就可以執(zhí)行數(shù)據(jù)庫更新了

    //6. 提交事務(wù)
    transaction.commit();
    //7. 關(guān)閉資源
    session.close();
    System.out.println("user:"+user);
}

二咪橙、 Hibernate的一級(jí)緩存

緩存的概念:介于應(yīng)用程序與永久性存儲(chǔ)的數(shù)據(jù)源之間夕膀,作用是降低應(yīng)用程序直接讀寫數(shù)據(jù)源的頻率,從而提高應(yīng)用的運(yùn)行性能。緩存中的數(shù)據(jù)是數(shù)據(jù)源數(shù)據(jù)的拷貝美侦。

1. 什么是Hibernate的一級(jí)緩存

  • Hibernate的一級(jí)緩存就是指Session緩存,Session緩存就是一塊內(nèi)存空間产舞。
  • 在使用Hibernate查詢對象時(shí),首先會(huì)拿該對象的OID去Session緩存中查找是否有匹配該OID值的對象。如果有就從Session緩存中取出使用,不再查詢數(shù)據(jù)庫音榜。如果沒有找到,就會(huì)去數(shù)據(jù)庫中查詢庞瘸。
  • 當(dāng)從數(shù)據(jù)庫查詢到數(shù)據(jù)時(shí),也會(huì)在Session緩存區(qū)放置一份該對象的數(shù)據(jù)信息,下次再查詢就可以在Session緩存中直接查詢到。

    @Test
    //測試一級(jí)緩存的存在
    public void test() {
        //首先獲取到一個(gè)對象,再重復(fù)獲取該對象,查看會(huì)打印幾次sql語句
        
        //1. 獲取Hibernate配置對象加載配置
        //2. 獲取SessionFactory工廠對象
        //3. 獲取Session對象
        Session session = HibernateUtils.openSession();
        //4. 開啟事務(wù)
        Transaction transaction = session.beginTransaction();
        //5. 實(shí)現(xiàn)業(yè)務(wù)邏輯
        
        User user = session.get(User.class, 1);
        System.out.println(user);
        User user2 = session.get(User.class, 1);
        System.out.println(user2);
        User user3 = session.get(User.class, 1);
        System.out.println(user3);
        
        
        //6. 提交事務(wù)
        transaction.commit();
        //7. 釋放資源
        session.close();
    }

結(jié)果只執(zhí)行了一次查詢語句,說明Hibernate只去數(shù)據(jù)庫查詢了一次獲取到了user對象,然后將該對象的數(shù)據(jù)信息存入了Session緩存中,在這個(gè)Session沒有關(guān)閉前,都可以從緩存中直接取出與該OID匹配的user對象赠叼。

img10.png

Hibernate的一級(jí)緩存(Session緩存)的特點(diǎn):

  1. 當(dāng)應(yīng)用程序調(diào)用Session接口的save()擦囊、update()违霞、saveOrUpdate()時(shí),如果緩存區(qū)中沒有對應(yīng)的對象,Hibernate會(huì)自動(dòng)的將從數(shù)據(jù)庫查詢到的相應(yīng)的對象信息加入到Session緩存中去瞬场。

  2. 當(dāng)調(diào)用Session接口的load()买鸽、get()、以及Query接口的list()方法時(shí),會(huì)判斷緩存中是否存在該對象,有則返回贯被,不會(huì)查詢數(shù)據(jù)庫眼五。如果緩存中沒有要查詢的對象,就去數(shù)據(jù)庫中查詢并放入Session緩存中。

  3. 當(dāng)調(diào)用Session對象的close()彤灶,Session緩存會(huì)被清空看幼。

2. Session緩存的快照區(qū)

Hibernate向一級(jí)緩存放入數(shù)據(jù)時(shí),同時(shí)會(huì)將一份數(shù)據(jù)放到Hibernate快照中,當(dāng)事務(wù)提交時(shí),
同時(shí)會(huì)清理Session的一級(jí)緩存,這時(shí)Hibernate會(huì)根據(jù)OID比較一級(jí)緩存與快照中的對象是否一致,
如果不一致執(zhí)行update語句。如果一致就不執(zhí)行幌陕。
Hibernate的快照確保了一級(jí)緩存中的數(shù)據(jù)與數(shù)據(jù)庫中數(shù)據(jù)的一致诵姜。

這也是Hibernate中持久化對象自動(dòng)更新數(shù)據(jù)庫的原理。

三搏熄、 Hibernate的事務(wù)控制

事務(wù):邏輯上的一組操作,組成這組操作的各個(gè)單元,要不全都成功,要不全都失敗棚唆。

1. 事務(wù)的四個(gè)特性:(ACID特性)

  • 原子性(Automic):表示將事務(wù)所做的操作捆綁成一個(gè)不可分割的單元。對事務(wù)所進(jìn)行的數(shù)據(jù)修改等操作,要不全都成功,要不全都失敗心例。

  • 一致性(Consistency):表示事務(wù)完成后,必須使所有的數(shù)據(jù)都保持一致狀態(tài)宵凌。

  • 隔離性(Isolation):一個(gè)事務(wù)的執(zhí)行不能被其他事務(wù)干擾,并發(fā)執(zhí)行的事務(wù)之間不能互相干擾。

  • 持久性(Durability):事務(wù)一旦提交,它對數(shù)據(jù)庫中數(shù)據(jù)的修改是永久性的止后。提交后的其他操作或者故障都不會(huì)有任何故障瞎惫。

2. 事務(wù)的并發(fā)問題

  1. 臟讀

     一個(gè)事務(wù)提交到了另一個(gè)事務(wù)未提交的數(shù)據(jù)。這是很嚴(yán)重的并發(fā)問題,必須解決坯门。
     例如:
         用戶購物,付款尚未成功提交之前微饥,賣家就能讀到用戶付款的數(shù)據(jù),誤以為已經(jīng)付款。
    
  2. 不可重復(fù)讀

     一個(gè)事務(wù)讀到了另一個(gè)事務(wù)已經(jīng)提交后的update的數(shù)據(jù),導(dǎo)致在同一個(gè)事務(wù)中的多次查詢結(jié)果不一致古戴。
    
     例如:
         小王在刷卡的同時(shí),家人用他的銀行卡進(jìn)行了網(wǎng)上購物,導(dǎo)致小王刷卡前后兩次查詢的結(jié)果不一致欠橘。
    
  3. 虛讀

     一個(gè)事務(wù)都到了另一個(gè)事務(wù)已經(jīng)提交的insert的數(shù)據(jù),導(dǎo)致在同一個(gè)事務(wù)中的多次查詢結(jié)果不一致。
    

3. 事務(wù)的4個(gè)隔離級(jí)別

為了避免事務(wù)并發(fā)問題的發(fā)生,標(biāo)準(zhǔn)sql規(guī)范中定義了4個(gè)事務(wù)隔離級(jí)別,不同的隔離級(jí)別對事務(wù)的處理不同现恼。

  1. 讀未提交肃续。(Read Uncommitted,1級(jí)),一個(gè)事務(wù)可以訪問其他事務(wù)未提交的數(shù)據(jù)。
  2. 讀已提交叉袍。(Read Commited,2級(jí)),一個(gè)事務(wù)在執(zhí)行的過程中,可以訪問其他事務(wù)成功提交的新插入的數(shù)據(jù),也可以訪問成功修改的數(shù)據(jù)始锚。但禁止訪問未提交的數(shù)據(jù)。該隔離級(jí)別可以有效的防止臟讀喳逛。
  3. 可重復(fù)讀瞧捌。(Repeatable Read,4級(jí)), 一個(gè)事務(wù)在執(zhí)行的過程中,可以訪問其他事務(wù)成功提交的新插入的數(shù)據(jù),但不可以訪問成功修改的數(shù)據(jù)。此隔離級(jí)別可以有效的防止臟讀與不可重復(fù)讀姐呐。
  4. 序列化殿怜。(Serializable,8級(jí)),提供嚴(yán)格的事務(wù)隔離,事務(wù)只能序列化,一個(gè)一個(gè)的執(zhí)行曙砂,不能并發(fā)執(zhí)行头谜。此隔離級(jí)別可以防止臟讀,不可重復(fù)讀以及虛讀鸠澈。

隔離級(jí)別越高柱告,安全性越高,性能越低。

mysql的隔離級(jí)別默認(rèn)是可重復(fù)讀(Repeatable Read)
oracle的隔離級(jí)別默認(rèn)是可重復(fù)讀(Read Committed)

4. Hibernate的事務(wù)管理

<!-- 
    設(shè)置隔離級(jí)別:
        hibernate.connection.isolation = 4
        1-Read uncommitted isolation
        2-Read committed isolation
        4-Repeatable read isolation
        8-Serializable isolation 
-->
<property name="hibernate.connection.isolation">4</property>

在使用Hibernate進(jìn)行事務(wù)管理時(shí),service層與dao層要保證Session對象的一致,可以采用三種方式確保Session
對象的一致: Session對象傳遞,使用ThreadLocal存儲(chǔ)與當(dāng)前線程綁定的Session對象,直接使用Hibernate封裝好的getCurrentSession()方法笑陈。


在這里,前兩種方式就省略了,如果有想了解的,可以翻看我以前寫的Connection部分JDBCUtils工具類的封裝际度。

直接使用Hibernate封裝好的管理Session的方式

在Hibernate的配置文件中,hibernate.current_session_context_class屬性用于指定Session的管理方式:

  • thread : Session對象的生命周期與當(dāng)前線程綁定
  • jta : Session對象的生命周期與JTA事務(wù)綁定
  • managed : Hibernate委托程序來管理Session的生命周期

hibernate.cfg.xml進(jìn)行如下配置:

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

配置后,Hibernate提供了getCurrentThread()方法來創(chuàng)建一個(gè)與當(dāng)前線程綁定的Session對象。

在HibernateUtils工具類中添加getCurrentSession方法:

// 獲得當(dāng)前線程中的綁定的Session
// 注意:必須配置
// return
public static Session getCurrentSession() {
    return sf.getCurrentSession();
}

需要注意的是:必須先在配置中進(jìn)行配置,而且使用后無需手動(dòng)關(guān)閉Session對象,事務(wù)提交后會(huì)自動(dòng)關(guān)閉Session對象


    Sercice層:

    //用戶轉(zhuǎn)賬的業(yè)務(wù)
    public void transfer(String sender, String receiver, String amount) throws Exception {
        Transaction transaction = null;
        try {
            //調(diào)用dao層
            TransferDAO dao = new TransferDAOImpl();
            
            //由于這里操作了兩條sql語句因此應(yīng)該開啟事務(wù)
            Session session = HibernateUtils.getCurrentSession();
            transaction = session.beginTransaction();
            
            //轉(zhuǎn)出
            dao.out(sender,amount);
            //轉(zhuǎn)入
            dao.in(receiver,amount);
            
            //沒有異常就提交
            transaction.commit();
        } catch (Exception e) {
            //回滾事務(wù)
            transaction.rollback();
            e.printStackTrace();
            throw e;
        }
    }


    dao 層:

    // 轉(zhuǎn)出
    public void out(String sender, String amount) throws SQLException {
        Session session = HibernateUtils.getCurrentSession();
        // 轉(zhuǎn)出
        User user = session.get(User.class, 1);
        double amount2 = Double.parseDouble(amount);
        user.setAcount(user.getAcount() - amount2);
    }

    @Override
    // 轉(zhuǎn)入
    public void in(String receiver, String amount) throws SQLException {
        Session session = HibernateUtils.getCurrentSession();
        // 轉(zhuǎn)入
        User user = session.get(User.class, 2);
        double amount2 = Double.parseDouble(amount);
        user.setAcount(user.getAcount() + amount2);
    }   

四涵妥、 Hibernate的批量查詢(概述)

1. HQL查詢 : Hibernate Query Language

HQL : Hibernate Query Language甲脏。Hibernate的獨(dú)家查詢語言,屬于面向?qū)ο蟮牟樵冋Z言。

適用于:多表查詢,但不是很復(fù)雜時(shí)使用妹笆。

  • setXxx : 如果HQL語句中有參數(shù),根據(jù)參數(shù)的不同類型設(shè)置參數(shù)的值。
  • setParameter : 上面方法的萬金油版本娜氏∪可以根據(jù)參數(shù)自動(dòng)選擇參數(shù)的類型設(shè)置。
  • uniqueResult : 結(jié)果只有一條記錄的時(shí)候使用,用于獲取唯一的結(jié)果贸弥。
  • list : 獲取多條記錄存儲(chǔ)在List集合中窟坐。
  • setFirstResult : 分頁查詢設(shè)置第一條記錄的位置。表示從第幾條數(shù)據(jù)查詢,默認(rèn)從0開始绵疲。
  • setMaxResult : 分頁查詢設(shè)置結(jié)果集的最大記錄數(shù)哲鸳。即每頁顯示的最大數(shù)據(jù)數(shù)量。

使用HQL的步驟:

  1. 獲取Session對象,開啟事務(wù)
  2. 編寫HQL語句
  3. 使用Session對象獲取查詢對象Query
  4. 如果HQL語句包含參數(shù),使用query.setXxx()設(shè)置參數(shù)盔憨。
    • 這里有一個(gè)萬金油的設(shè)置參數(shù)的方法. query.setParameter()徙菠;
  5. 執(zhí)行HQL查詢語句

HQL查詢測試


    /**
     * Hibernate的HQL語句練習(xí)
     */
    public class HibernateTest {
    
        @Test
        // HQL基本查詢
        public void test() {
            // 1. 獲取Session對象
            Session session = HibernateUtils.getCurrentSession();
            // 2.開啟事務(wù)
            Transaction transaction = session.beginTransaction();
            // -----------------------------------------
            // 3. 業(yè)務(wù)邏輯:HQL的基本查詢
    
            // 3.1 創(chuàng)建HQL查詢語句。HQL語句格式為:select * from 全類名.
            // HQL語句格式為:select * from 全類名.
            // 在查詢所有字段時(shí)可以省略select *
            // String hql = "select * from com.itdream.domain.Customer";
            String hql = "from Customer";
            // 3.2 創(chuàng)建查詢對象Query
            Query query = session.createQuery(hql);
            // 3.3 執(zhí)行查詢
            List<Customer> list = query.list();
            // 如果確定結(jié)果為一條結(jié)果,可以使用uniqeResult()
            // Customer customer = (Customer) query.uniqueResult();
    
            System.out.println(list);
    
            // -----------------------------------------
            // 4.提交事務(wù)
            transaction.commit();
            // getCurrentSession無需手動(dòng)關(guān)閉
        }
    
        @Test
        // HQL條件查詢:問號(hào)占位符
        public void test2() {
            // 1. 獲取Session對象
            Session session = HibernateUtils.getCurrentSession();
            // 2.開啟事務(wù)
            Transaction transaction = session.beginTransaction();
            // -----------------------------------------
            // 3. 業(yè)務(wù)邏輯:HQL條件查詢:問號(hào)占位符
            // 3.1 編寫HQL查詢語句,注意:HQL語句中出現(xiàn)的是類中的屬性而不是表中的字段
            String hql = "from Customer where cid = ?";
            //3.2 獲取HQL的查詢對象Query
            Query query = session.createQuery(hql);
            //設(shè)置問號(hào)占位符處的參數(shù).Hibernate的問號(hào)占位付默認(rèn)從0開始
            //query.setInteger(0, 2);
            //萬金油的設(shè)置參數(shù)方法
            query.setParameter(0, 2);
            //3.3 執(zhí)行查詢
            Customer customer = (Customer) query.uniqueResult();
            
            System.out.println(customer);
            // -----------------------------------------
            // 4.提交事務(wù)
            transaction.commit();
            // getCurrentSession無需手動(dòng)關(guān)閉
        }
        
        @Test
        // HQL條件查詢:命名占位符
        public void test3() {
            // 1. 獲取Session對象
            Session session = HibernateUtils.getCurrentSession();
            // 2.開啟事務(wù)
            Transaction transaction = session.beginTransaction();
            // -----------------------------------------
            // 3. 業(yè)務(wù)邏輯:HQL條件查詢:命名占位符(冒號(hào):+命名)
            // 3.1 編寫HQL查詢語句,注意:HQL語句中出現(xiàn)的是類中的屬性而不是表中的字段
            String hql = "from Customer where cid = :cid";
            //3.2 獲取HQL的查詢對象Query
            Query query = session.createQuery(hql);
            //設(shè)置問號(hào)占位符處的參數(shù).Hibernate的問號(hào)占位付默認(rèn)從0開始
            //萬金油的設(shè)置參數(shù)方法
            query.setParameter("cid", 2);
            //3.3 執(zhí)行查詢
            Customer customer = (Customer) query.uniqueResult();
            
            System.out.println(customer);
            // -----------------------------------------
            // 4.提交事務(wù)
            transaction.commit();
            // getCurrentSession無需手動(dòng)關(guān)閉
        }
        
        
        @Test
        // HQL分頁查詢
        public void test4() {
            // 1. 獲取Session對象
            Session session = HibernateUtils.getCurrentSession();
            // 2.開啟事務(wù)
            Transaction transaction = session.beginTransaction();
            // -----------------------------------------
            // 3. 業(yè)務(wù)邏輯:HQL條件查詢:命名占位符(冒號(hào):+命名)
            // 3.1 編寫HQL查詢語句,注意:HQL語句中出現(xiàn)的是類中的屬性而不是表中的字段
            String hql = "from Customer";
            //3.2 獲取查詢對象Query
            Query query = session.createQuery(hql);
            
            //3.3 設(shè)置分頁的參數(shù)
            query.setFirstResult(4);//從第(4+1)條數(shù)據(jù)開始,Hibernate默認(rèn)從0開始
            query.setMaxResults(2);//每頁顯示兩條數(shù)據(jù)
            
            //3.4執(zhí)行hql語句
            List<Customer> list = query.list();
            System.out.println(list);
            // -----------------------------------------
            // 4.提交事務(wù)
            transaction.commit();
            // getCurrentSession無需手動(dòng)關(guān)閉
        }
    }

分頁查詢結(jié)果:

img11.png

2. Critiria查詢

Criteria查詢是Hibernate的核心查詢對象郁岩。它是完全面向?qū)ο蟮臒o語句查詢婿奔。在Criteria查詢方式中,是絕對不會(huì)出現(xiàn)sql語句的。Criteria查詢又稱為QBC查詢(Query By Criteria)问慎。

適用于單表的條件查詢萍摊。


常用API

//獲取Criteria查詢對象
Criteria criteria = session.createCriteria(Customer.class); //傳入的參數(shù)是持久化類對象

//設(shè)置查詢條件
// 參數(shù)1:持久化類中的屬性 。 參數(shù)2:對應(yīng)的值
Criterion eq = Restrictions.eq("cid", 1);

//設(shè)置分頁參數(shù)
criteria.setFirstResult(4);//這里的4代表的是索引,第五條記錄開始
criteria.setMaxResults(2);//每頁顯示2條數(shù)據(jù)

//查詢總記錄數(shù)
criteria.setProjection(Projections.rowCount());

//執(zhí)行查詢
List<Customer> list = criteria.list();
Customer customer = (Customer) criteria.uniqueResult();

Criteria查詢的步驟:

  1. 獲取Session對象,開啟事務(wù)
  2. 獲取查詢對象Criteria
  3. 如果有限制條件使用Restrictions添加限制條件
  4. 如果是分頁查詢使用criteria.setFirstResult或setMaxResult方法設(shè)置分頁參數(shù)
  5. Restrictions設(shè)置的限制條件添加到查詢對象Criteria
  6. 執(zhí)行查詢

Criteria查詢測試:


    @Test
    // Criteria基本查詢 :查詢所有數(shù)據(jù)
    public void test() {
        // 1. 獲取Session對象
        Session session = HibernateUtils.getCurrentSession();
        // 2.開啟事務(wù)
        Transaction transaction = session.beginTransaction();
        // -----------------------------------------
        // 3. 業(yè)務(wù)邏輯:Criteria的基本查詢
        // 3.1 獲取Criteria查詢對象
        Criteria criteria = session.createCriteria(Customer.class);
        // 3.2 執(zhí)行查詢
        List<Customer> list = criteria.list();
        // Customer customer = (Customer) criteria.uniqueResult();

        System.out.println(list);
        // -----------------------------------------
        // 4.提交事務(wù)
        transaction.commit();
        // getCurrentSession無需手動(dòng)關(guān)閉
    }

    @Test
    // Criteria條查詢
    public void test2() {
        // 1. 獲取Session對象
        Session session = HibernateUtils.getCurrentSession();
        // 2.開啟事務(wù)
        Transaction transaction = session.beginTransaction();
        // -----------------------------------------
        // 3. 業(yè)務(wù)邏輯:Criteria的條件查詢
        // 3.1 獲取Criteria查詢對象
        Criteria criteria = session.createCriteria(Customer.class);
        // 3.2 設(shè)置查詢限制條件
        // 參數(shù)1:持久化類中的屬性 如叼。 參數(shù)2:對應(yīng)的值
        Criterion eq = Restrictions.eq("cid", 1);
        Criterion eq2 = Restrictions.eq("cname", "唐嫣");

        // 添加限制條件到查詢對象中(可以添加多個(gè)限制條件)
        criteria.add(eq);
        criteria.add(eq2);

        // 3.3 執(zhí)行查詢操作
        // List<Customer> list = criteria.list();
        Customer customer = (Customer) criteria.uniqueResult();
        System.out.println(customer);
        // -----------------------------------------
        // 4.提交事務(wù)
        transaction.commit();
        // getCurrentSession無需手動(dòng)關(guān)閉
    }

    @Test
    // Criteria分頁查詢
    public void test3() {
        // 1. 獲取Session對象
        Session session = HibernateUtils.getCurrentSession();
        // 2.開啟事務(wù)
        Transaction transaction = session.beginTransaction();
        // -----------------------------------------
        // 3. 業(yè)務(wù)邏輯:Criteria的分頁查詢
        // 3.1 獲取Criteria查詢對象
        Criteria criteria = session.createCriteria(Customer.class);
        //3.2 設(shè)置分頁參數(shù)
        criteria.setFirstResult(4);//這里的4代表的是索引,第五條記錄開始
        criteria.setMaxResults(2);//每頁顯示2條數(shù)據(jù)
        //3.3 執(zhí)行查詢
        List<Customer> list = criteria.list();
        System.out.println(list);
        // -----------------------------------------
        // 4.提交事務(wù)
        transaction.commit();
        // getCurrentSession無需手動(dòng)關(guān)閉
    }


    @Test
    // Criteria查詢總記錄數(shù)
    public void test4() {
        // 1. 獲取Session對象
        Session session = HibernateUtils.getCurrentSession();
        // 2.開啟事務(wù)
        Transaction transaction = session.beginTransaction();
        // -----------------------------------------
        // 3. 業(yè)務(wù)邏輯:Criteria的分頁查詢
        // 3.1 獲取Criteria查詢對象
        Criteria criteria = session.createCriteria(Customer.class);
        // 3.2 獲取總記錄數(shù)
        criteria.setProjection(Projections.rowCount());
        //3.3 執(zhí)行查詢操作獲取總記錄數(shù)
        Long rows = (Long) criteria.uniqueResult();
        
        System.out.println(rows);
        // -----------------------------------------
        // 4.提交事務(wù)
        transaction.commit();
        // getCurrentSession無需手動(dòng)關(guān)閉
    }

附常用Restrictions的靜態(tài)方法:

常見的Restrictions的靜態(tài)方法
    方法                  說明
    Restrictions.eq         =
    Restrictions.allEq      利用Map來進(jìn)行多個(gè)等于的限制
    Restrictions.gt         >(greater than)
    Restrictions.ge         >=(greater than or equal)
    Restrictions.lt         < (less than)
    Restrictions.le         <=(less than or equal)
    Restrictions.between    BETWEEN
    Restrictions.like       LIKE
    Restrictions.in         in
    Restrictions.and        and
    Restrictions.or         or
    Restrictions.sqlRestriction 用SQL限定查詢

3. SQLQuery查詢(原生的SQL語句查詢)

適用于復(fù)雜的多表業(yè)務(wù)查詢

常用API:

//創(chuàng)建SQLQuery查詢對象
SQLQuery query = session.createSQLQuery(sql);

//指定將結(jié)果集封裝到某個(gè)對象中
query.addEntity(Customer.class);

//執(zhí)行sql語句
List<Customer> list = query.list();
Customer customer = (Long)query.uniqueResult();

SQLQuery查詢測試:


    @Test
    // SQLQuery基本查詢 :查詢所有數(shù)據(jù)(返回Object數(shù)組的List)
    public void test() {
        // 1. 獲取Session對象
        Session session = HibernateUtils.getCurrentSession();
        // 2.開啟事務(wù)
        Transaction transaction = session.beginTransaction();
        // -----------------------------------------

        // 3. 業(yè)務(wù)邏輯:SQLQuery的基本查詢:查詢所有數(shù)據(jù)
        // 3.1 編寫sql語句
        String sql = "select * from customer";

        // 3.2 獲取SQLQuery查詢對象
        SQLQuery query = session.createSQLQuery(sql);

        // 3.3 執(zhí)行查詢,返回的結(jié)果是一個(gè)List集合
        // 每條記錄的查詢結(jié)果作為Object數(shù)組的元素冰木。將所有的記錄Object數(shù)組存入List集合
        List<Object[]> list = query.list();

        for (Object[] objects : list) {
            System.out.println(Arrays.toString(objects));
        }

        // -----------------------------------------
        // 4.提交事務(wù)
        transaction.commit();
        // getCurrentSession無需手動(dòng)關(guān)閉
    }


img12.png

    @Test
    // SQLQuery基本查詢 :查詢所有數(shù)據(jù)(返回Customer的List)
    public void test2() {
        // 1. 獲取Session對象
        Session session = HibernateUtils.getCurrentSession();
        // 2.開啟事務(wù)
        Transaction transaction = session.beginTransaction();
        // -----------------------------------------

        // 3. 業(yè)務(wù)邏輯:SQLQuery的基本查詢:查詢所有數(shù)據(jù)
        // 3.1 編寫sql語句
        String sql = "select * from customer";
        // 3.2 創(chuàng)建SQLQuery查詢對象
        SQLQuery query = session.createSQLQuery(sql);
        // 3.3 指定將結(jié)果集封裝到某個(gè)對象中
        query.addEntity(Customer.class);
        // 3.4 執(zhí)行sql語句
        List<Customer> list = query.list();

        System.out.println(list);

        // -----------------------------------------
        // 4.提交事務(wù)
        transaction.commit();
        // getCurrentSession無需手動(dòng)關(guān)閉
    }
img13.png

    @Test
    // SQLQuery條件查詢
    public void test3() {
        // 1. 獲取Session對象
        Session session = HibernateUtils.getCurrentSession();
        // 2.開啟事務(wù)
        Transaction transaction = session.beginTransaction();
        // -----------------------------------------

        // 3. 業(yè)務(wù)邏輯:SQLQuery的基本查詢:查詢所有數(shù)據(jù)
        // 3.1 編寫sql語句
        String sql = "select * from customer where cid = ?";
        // 3.2 創(chuàng)建SQLQuery查詢對象
        SQLQuery query = session.createSQLQuery(sql);
        // 設(shè)置參數(shù)的值。參數(shù)1:第幾個(gè)數(shù)據(jù)。參數(shù)2:對應(yīng)的值
        query.setParameter(0, 1);
        // 3.3 指定將結(jié)果集封裝到某個(gè)對象中
        query.addEntity(Customer.class);
        // 3.4 執(zhí)行sql語句
        Customer customer = (Customer) query.uniqueResult();

        System.out.println(customer);

        // -----------------------------------------
        // 4.提交事務(wù)
        transaction.commit();
        // getCurrentSession無需手動(dòng)關(guān)閉
    }


    @Test
    // SQLQuery分頁查詢:方式1:傳統(tǒng)sql語句
    public void test4() {
        // 1. 獲取Session對象
        Session session = HibernateUtils.getCurrentSession();
        // 2.開啟事務(wù)
        Transaction transaction = session.beginTransaction();
        // -----------------------------------------

        // 3. 業(yè)務(wù)邏輯:SQLQuery的基本查詢:查詢所有數(shù)據(jù)
        // 3.1 編寫sql語句
        String sql = "select * from customer limit ?,?";
        // 3.2 創(chuàng)建SQLQuery查詢對象
        SQLQuery query = session.createSQLQuery(sql);

        // 設(shè)置分頁查詢的參數(shù)
        query.setParameter(0, 4);
        query.setParameter(1, 2);

        // 3.3 指定將結(jié)果集封裝到某個(gè)對象中
        query.addEntity(Customer.class);
        // 3.4 執(zhí)行sql語句
        List<Customer> list = query.list();

        System.out.println(list);

        // -----------------------------------------
        // 4.提交事務(wù)
        transaction.commit();
        // getCurrentSession無需手動(dòng)關(guān)閉
    }


    @Test
    // SQLQuery分頁查詢:方式2:setFirstResult()方法
    public void test5() {
        // 1. 獲取Session對象
        Session session = HibernateUtils.getCurrentSession();
        // 2.開啟事務(wù)
        Transaction transaction = session.beginTransaction();
        // -----------------------------------------

        // 3. 業(yè)務(wù)邏輯:SQLQuery的基本查詢:查詢所有數(shù)據(jù)
        // 3.1 編寫sql語句
        String sql = "select * from customer";
        // 3.2 創(chuàng)建SQLQuery查詢對象
        SQLQuery query = session.createSQLQuery(sql);

        // 設(shè)置分頁查詢的參數(shù)
        query.setFirstResult(4);// 設(shè)置從第幾個(gè)數(shù)據(jù)開始查詢,默認(rèn)從0開始
        query.setMaxResults(2);// 設(shè)置每頁顯示的數(shù)據(jù)條數(shù)

        // 3.3 指定將結(jié)果集封裝到某個(gè)對象中
        query.addEntity(Customer.class);
        // 3.4 執(zhí)行sql語句
        List<Customer> list = query.list();

        System.out.println(list);

        // -----------------------------------------
        // 4.提交事務(wù)
        transaction.commit();
        // getCurrentSession無需手動(dòng)關(guān)閉
    }

4. 簡單的CRM查詢案例

步驟:

1. 搭建工程環(huán)境

1. 創(chuàng)建工程,導(dǎo)入jar包,拷貝頁面等文件

2. 創(chuàng)建數(shù)據(jù)庫表cst_customer

3. 創(chuàng)建持久化類Customer

4. 創(chuàng)建持久化類和數(shù)據(jù)庫表的映射文件Customer.hbm.xml

5. 創(chuàng)建Hibernate的核心配置文件hibernate.cfg.xml

6. 完成核心配置文件中c3p0的配置,創(chuàng)建log4j.properties配置文件

7. 編寫工具類HibernateUtils踊沸,環(huán)境搭建完畢
1.1.導(dǎo)入jar包

包含有:

  • 數(shù)據(jù)庫驅(qū)動(dòng)
  • Hibernate必需包下的所有jar包
  • Hibernate的c3p0中的3個(gè)jar包
  • 日志集成slf4j和log4j的3個(gè)jar包
  • jstl.jar與standard.jar的jstl標(biāo)簽庫jar包
img14.png
1.2 創(chuàng)建數(shù)據(jù)庫表

    CREATE DATABASE hibernate_crm;
    
    USE hibernate_crm;
    
    CREATE TABLE `cst_customer` (
      `cust_id` BIGINT(32) NOT NULL AUTO_INCREMENT COMMENT '客戶編號(hào)(主鍵)',
      `cust_name` VARCHAR(32) NOT NULL COMMENT '客戶名稱(公司名稱)',
      `cust_user_id` BIGINT(32) DEFAULT NULL COMMENT '負(fù)責(zé)人id',
      `cust_create_id` BIGINT(32) DEFAULT NULL COMMENT '創(chuàng)建人id',
      `cust_source` VARCHAR(32) DEFAULT NULL COMMENT '客戶信息來源',
      `cust_industry` VARCHAR(32) DEFAULT NULL COMMENT '客戶所屬行業(yè)',
      `cust_level` VARCHAR(32) DEFAULT NULL COMMENT '客戶級(jí)別',
      `cust_linkman` VARCHAR(64) DEFAULT NULL COMMENT '聯(lián)系人',
      `cust_phone` VARCHAR(64) DEFAULT NULL COMMENT '固定電話',
      `cust_mobile` VARCHAR(16) DEFAULT NULL COMMENT '移動(dòng)電話',
      PRIMARY KEY (`cust_id`)
    ) ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
    
    INSERT INTO cst_customer(cust_id,cust_name) 
    VALUES(NULL,'唐嫣'),(NULL,'鐘漢良'),(NULL,'林心如'),
    (NULL,'霍建華'),(NULL,'楊冪'),(NULL,'劉愷威'),
    (NULL,'高圓圓'),(NULL,'趙又廷');
1.3 創(chuàng)建持久化類

與數(shù)據(jù)庫表基本保持一致歇终,按照持久化類的編寫規(guī)則編寫。

img15.png
1.4 創(chuàng)建持久化類和數(shù)據(jù)庫表的映射文件Customer.hbm.xml

步驟:

  1. 在持久化類的同級(jí)目錄下,創(chuàng)建xml文件,取名類名.hbm.xml雕沿。這里名字為:Customer.hbm.xml
  2. 導(dǎo)入DTD約束练湿。從jar包中可以找到DTD的約束描述,copy過來
  3. 創(chuàng)建持久化類與數(shù)據(jù)庫表的映射
  4. 創(chuàng)建持久化類中標(biāo)識(shí)符OID與數(shù)據(jù)庫表的主鍵的映射
  5. 創(chuàng)建類中普通屬性與數(shù)據(jù)庫表的字段的映射

    <?xml version="1.0" encoding="UTF-8"?>
    
    <!-- 建立持久化類Customer與數(shù)據(jù)庫表customer的映射關(guān)系的配置文件 -->
    
    <!-- 引入DTD約束 -->
    <!DOCTYPE hibernate-mapping PUBLIC 
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
        
     <hibernate-mapping>
        <!-- 建立持久化類與表的映射關(guān)系 -->
        <class name="com.itdream.domain.Customer" table="cst_customer">
            <!-- 配置持久化類OID與表的主鍵的映射 -->
            <id name="cust_id" column="cust_id">
                <!-- 配置主鍵生成策略 -->
                <generator class="native"></generator>
            </id>
            
            <!-- 配置普通字段的映射關(guān)系 -->    
            <property name="cust_name" column="cust_name"></property>
        </class>
     </hibernate-mapping>
1.5 創(chuàng)建Hibernate的核心配置文件hibernate.cfg.xml

步驟:

  1. 在src目錄下創(chuàng)建文件名為hibernate.cfg.xml的配置文件
  2. 導(dǎo)入DTD約束
  3. 配置Hibernate連接數(shù)據(jù)庫的基本配置
  4. 配置Session與當(dāng)前線程綁定
  5. 配置Hibernate基本屬性,包括:
    1. Hibernate方言,根據(jù)這個(gè)配置Hiberante使用對應(yīng)的sql語句,實(shí)現(xiàn)了跨數(shù)據(jù)庫
    2. 顯示SQL語句
    3. 格式化SQL語句
    4. 配置Hibernate對應(yīng)數(shù)據(jù)庫表的生成方式hbm2ddl
    5. 配置數(shù)據(jù)庫的隔離級(jí)別
    6. c3p0連接池的配置
  6. 加載映射文件

    <?xml version="1.0" encoding="UTF-8"?>
    
    <!-- 導(dǎo)入Hibernate核心配置文件的DTD約束 -->
    <!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
    
    <!-- 配置Hibernate的核心配置文件 -->
    <hibernate-configuration>
        <session-factory>
            <!--1. Hibernate連接數(shù)據(jù)庫的基本配置 -->
            <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
            <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/hibernate_crm</property>
            <property name="hibernate.connection.username">root</property>
            <property name="hibernate.connection.password">root</property>
    
            <!--2. Session與本地線程綁定 -->
            <property name="hibernate.current_session_context_class">thread</property>
    
            <!--3. Hibernate的基本屬性配置 -->
            <!-- Hibernate的方言配置,Hibernate根據(jù)這個(gè)配置生成對應(yīng)的SQL語句,從而實(shí)現(xiàn)跨數(shù)據(jù)庫 -->
            <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
    
            <!-- 顯示SQL語句 -->
            <property name="hibernate.show_sql">true</property>
            <!-- 格式化SQL語句 -->
            <property name="hibernate.format_sql">true</property>
            <!-- Hibernate對數(shù)據(jù)庫表的生成方式,hbm2ddl -->
            <property name="hibernate.hbm2ddl.auto">none</property>
    
            <!-- 配置隔離級(jí)別 :4 讀可重復(fù)(Repeatable read) -->
            <property name="hibernate.connection.isolation">4</property>
    
            <!-- C3P0連接池的配置 -->
            <property name="hibernate.connection.provider_class">org.hibernate.c3p0.internal.C3P0ConnectionProvider</property>
            <!-- 最小連接 -->
            <property name="hibernate.c3p0.min_size">5</property>
            <!-- 最大連接數(shù) -->
            <property name="hibernate.c3p0.max_size">20</property>
            <!-- 連接超時(shí)時(shí)長 -->
            <property name="hibernate.c3p0.timeout">120</property>
            <!-- 每120秒檢查空閑連接 -->
            <property name="hibernate.c3p0.idle_test_period">120</property>
            <!-- 最大statments數(shù)量 -->
            <property name="hibernate.c3p0.max_statements">120</property>
            <!-- 連接用完后审轮,每次增加的連接數(shù) -->
            <property name="hibernate.c3p0.acquire_increment">2</property>
            <!-- 每次都驗(yàn)證連接是否可用 -->
            <property name="hibernate.c3p0.validate">false</property>
    
            <!--4. 加載映射文件 -->
            <mapping resource="com/itdream/domain/Customer.hbm.xml" />
        </session-factory>
    </hibernate-configuration>  
1.6 完成核心配置文件中c3p0的配置,創(chuàng)建log4j.properties配置文件

1. c3p0的配置見上一條1.5中核心配置文件.

2. log4j日志集成的配置文件log4j.properties

在src目錄下創(chuàng)建log4j.properties:


    ### direct log messages to stdout ###
    log4j.appender.stdout=org.apache.log4j.ConsoleAppender
    log4j.appender.stdout.Target=System.err
    log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
    log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
    
    ### direct messages to file mylog.log ###
    log4j.appender.file=org.apache.log4j.FileAppender
    log4j.appender.file.File=d:\\mylog.log
    log4j.appender.file.layout=org.apache.log4j.PatternLayout
    log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
    
    ### set log levels - for more verbose logging change 'info' to 'debug' ###
    log4j.rootLogger=info, stdout,file
1.7 編寫工具類HibernateUtils

    /**
     * 初始化SessionFactory,提供Session對象的Hibernate工具類
     */
    public class HibernateUtils {
    
        private static SessionFactory sf = null;
    
        static {
            // 創(chuàng)建Hibernate配置對象,加載src目錄下默認(rèn)的hibernate.cfg.xml配置文件
            Configuration configuration = new Configuration().configure();
            // 創(chuàng)建SessionFactory工廠對象
            sf = configuration.buildSessionFactory();
    
            // 程序關(guān)閉銷毀SessionFactory對象
            Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
    
                @Override
                public void run() {
                    System.out.println("程序關(guān)閉銷毀SessionFactory對象");
                    sf.close();
                }
            }));
        }
    
        /**
         * 獲取Session對象的方法
         */
        public static Session openSession() {
            return sf.openSession();
        }
    
        /**
         * 獲取與當(dāng)前線程綁定的Session對象
         */
        public static Session getCurrentSession() {
            return sf.getCurrentSession();
        }
    }

2. 代碼實(shí)現(xiàn),使用Hibernate的查詢語句查詢所有Customer

2.1 mennu.jsp修改a標(biāo)簽跳轉(zhuǎn)
    <TD class=menuSmall><A class=style2 href="customer?method=list"target=main>- 客戶列表</A></TD>
2.2 創(chuàng)建Servlet,映射url-pattern為servlet

    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        // 獲取傳遞過來的method參數(shù)
        String method = request.getParameter("method");

        if ("list".equals(method)) { // 如果是list,就查詢所有Customer客戶

            try {
                // 調(diào)用service層
                CustomerService service = new CustomerServiceImpl();
                List<Customer> list = service.findAllCustomers();

                // 存入request域
                request.setAttribute("list", list);
                System.out.println(list);
                
                // 轉(zhuǎn)發(fā)
                request.getRequestDispatcher("/jsp/customer/list.jsp").forward(request, response);;
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

    }
2.3 CustomerService層,調(diào)用dao層查詢所有Customer

    @Override
    public List<Customer> findAllCustomers() throws SQLException {
        //調(diào)用dao層查詢所有Customer用戶
        CustomerDAO dao = new CustomerDAOImpl();
        return dao.findAllCustomers();
    }
2.4 CustomerDAO層,查詢所有Customer返回

使用Criteria與HQL兩種查詢方式,單表查詢推薦使用Criteria查詢


    @Override
    // 方式1:顯示所有Customer的方法:Criteria查詢(單表查詢簡單)
    public List<Customer> findAllCustomers() throws SQLException {
        // 1. 獲取配置對象加載配置文件
        // 2. 獲取SessionFactory對象
        // 3. 獲取Session對象
        Session session = HibernateUtils.getCurrentSession();
        // 4. 開啟事務(wù)
        Transaction transaction = session.beginTransaction();
        // 5. 業(yè)務(wù)邏輯 :查詢所有Customer對象,單表查詢使用Criteria較為簡單
        // 5.1 創(chuàng)建Criteria查詢對象
        Criteria criteria = session.createCriteria(Customer.class);
        // 5.2 如果有條件就添加限制條件Restrictions,然后添加到查詢對象中
        // 5.3 執(zhí)行查詢
        List<Customer> list = criteria.list();

        // 6. 提交事務(wù)
        transaction.commit();
        // 7. getCurrentSession()無需手動(dòng)關(guān)閉Session對象
        return list;
    }
     

    /*@Override
    // 方式2:顯示所有Customer的方法:HQL查詢(常用于不是很復(fù)雜的多表查詢)
    public List<Customer> findAllCustomers() throws SQLException {

        // 1. 獲取配置對象加載配置文件
        // 2. 獲取SessionFactory對象
        // 3. 獲取Session對象
        Session session = HibernateUtils.getCurrentSession();
        // 4. 開啟事務(wù)
        Transaction transaction = session.beginTransaction();
        // 5. 業(yè)務(wù)邏輯 : 查詢所有Customer對象,單表查詢使用Criteria較為簡單
        // 5.1  編寫HQL語句,HQL語句中出現(xiàn)的都是持久化類中的屬性,而不是數(shù)據(jù)庫表中的字段
        String hql = "from Customer";
        // 5.2 創(chuàng)建HQL的Query對象
        Query query = session.createQuery(hql);
        // 5.3  如果hql語句中有參數(shù)使用setParameter()設(shè)置參數(shù)
        // 5.4  執(zhí)行hql語句
        List<Customer> list = query.list();
        // 6. 提交事務(wù)
        transaction.commit();
        // 7. getCurrentSession()無需手動(dòng)關(guān)閉Session對象
        return list;
    }*/
2.5 查詢結(jié)果肥哎,list頁面解析(這里省略)

查詢結(jié)果圖:

img16.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市疾渣,隨后出現(xiàn)的幾起案子篡诽,更是在濱河造成了極大的恐慌,老刑警劉巖榴捡,帶你破解...
    沈念sama閱讀 221,548評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件杈女,死亡現(xiàn)場離奇詭異,居然都是意外死亡吊圾,警方通過查閱死者的電腦和手機(jī)达椰,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,497評論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來项乒,“玉大人啰劲,你說我怎么就攤上這事√春危” “怎么了蝇裤?”我有些...
    開封第一講書人閱讀 167,990評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長频鉴。 經(jīng)常有香客問我栓辜,道長,這世上最難降的妖魔是什么垛孔? 我笑而不...
    開封第一講書人閱讀 59,618評論 1 296
  • 正文 為了忘掉前任藕甩,我火速辦了婚禮,結(jié)果婚禮上似炎,老公的妹妹穿的比我還像新娘辛萍。我一直安慰自己,他們只是感情好羡藐,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,618評論 6 397
  • 文/花漫 我一把揭開白布贩毕。 她就那樣靜靜地躺著,像睡著了一般仆嗦。 火紅的嫁衣襯著肌膚如雪辉阶。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,246評論 1 308
  • 那天,我揣著相機(jī)與錄音谆甜,去河邊找鬼垃僚。 笑死,一個(gè)胖子當(dāng)著我的面吹牛规辱,可吹牛的內(nèi)容都是我干的谆棺。 我是一名探鬼主播,決...
    沈念sama閱讀 40,819評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼罕袋,長吁一口氣:“原來是場噩夢啊……” “哼改淑!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起浴讯,我...
    開封第一講書人閱讀 39,725評論 0 276
  • 序言:老撾萬榮一對情侶失蹤朵夏,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后榆纽,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體仰猖,經(jīng)...
    沈念sama閱讀 46,268評論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,356評論 3 340
  • 正文 我和宋清朗相戀三年奈籽,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了饥侵。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,488評論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡衣屏,死狀恐怖爆捞,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情勾拉,我是刑警寧澤,帶...
    沈念sama閱讀 36,181評論 5 350
  • 正文 年R本政府宣布盗温,位于F島的核電站藕赞,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏卖局。R本人自食惡果不足惜斧蜕,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,862評論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望砚偶。 院中可真熱鬧批销,春花似錦、人聲如沸染坯。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,331評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽单鹿。三九已至掀宋,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背劲妙。 一陣腳步聲響...
    開封第一講書人閱讀 33,445評論 1 272
  • 我被黑心中介騙來泰國打工湃鹊, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人镣奋。 一個(gè)月前我還...
    沈念sama閱讀 48,897評論 3 376
  • 正文 我出身青樓币呵,卻偏偏與公主長得像,于是被迫代替她去往敵國和親侨颈。 傳聞我的和親對象是個(gè)殘疾皇子余赢,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,500評論 2 359

推薦閱讀更多精彩內(nèi)容

  • Hibernate是一個(gè)開放源代碼的對象關(guān)系映射框架,它對JDBC進(jìn)行了非常輕量級(jí)的對象封裝肛搬,它將POJO與數(shù)據(jù)庫...
    蘭緣小妖閱讀 1,213評論 1 18
  • 本文包括:1没佑、Hibernate的持久化類2、Hibernate 持久化對象的三個(gè)狀態(tài)(難點(diǎn))3温赔、Hibernat...
    廖少少閱讀 1,453評論 0 13
  • 1.主鍵生成策略 1.1 主鍵的兩種類型 自然主鍵:把數(shù)據(jù)表中的某一業(yè)務(wù)字段作為表的主鍵蛤奢。如一張用戶表中楼誓,把用戶的...
    Wizey閱讀 552評論 0 3
  • Hibernate: 一個(gè)持久化框架 一個(gè)ORM框架 加載:根據(jù)特定的OID,把一個(gè)對象從數(shù)據(jù)庫加載到內(nèi)存中OID...
    JHMichael閱讀 1,979評論 0 27
  • 記得剛來到中傳還是2015年的夏天居触,興奮的我來到孔子雕像前遐想拜秧,兩年后我的母校就是中國傳媒大學(xué)了痹屹,想到這里心里不免...
    新媒體小業(yè)閱讀 206評論 0 1