首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

Hibernate 實戰進階:工具類、CRUD、物件狀態、一級緩存、HQL/QBC/SQL 查詢全景指南

     編輯:Java 綜合教學

Hibernate 實戰進階:工具類、CRUD、物件狀態、一級緩存、HQL/QBC/SQL 查詢全景指南

本文系統整理 Hibernate 核心開發技能,涵蓋 SessionFactory 單例工具類、基礎增刪改查、三大物件狀態轉換、一級緩存機制、HQL/QBC/原生 SQL 多維查詢技術,附完整可執行測試代碼。

一、SessionFactory 單例工具類 (H3Util)

public class H3Util {
    private static final SessionFactory sessionFactory = buildSessionFactory();

    private static SessionFactory buildSessionFactory() {
        try {
            // 載入 classpath:hibernate.cfg.xml
            return new Configuration().configure().buildSessionFactory();
        } catch (Throwable ex) {
            throw new ExceptionInInitializerError(ex);
        }
    }

    public static SessionFactory getSessionFactory() {
        return sessionFactory;
    }
}

設計要點:SessionFactory 線程安全、重量級,全應用僅需一個實例;Session 輕量、非線程安全,請求級別開啟關閉。

二、基礎 CRUD 操作範本

public class TestHibernate {
    // 新增
    @Test public void add() {
        Session session = H3Util.getSessionFactory().openSession();
        Transaction tx = session.beginTransaction();
        for (int i = 0; i < 20; i++) {
            session.save(new User(null, "test"+i, "123456", new Date(), 1, 1000f));
        }
        tx.commit(); session.close();
    }

    // 查詢單筆 (get: 立即載入 / load: 延遲載入)
    @Test public void find() {
        Session session = H3Util.getSessionFactory().openSession();
        User user = (User) session.get(User.class, 1L); // 立即發 SQL
        // User user = (User) session.load(User.class, 1L); // 不發 SQL,用到屬性時才發
        session.close();
    }

    // 刪除
    @Test public void del() {
        Session session = H3Util.getSessionFactory().openSession();
        Transaction tx = session.beginTransaction();
        User user = (User) session.get(User.class, 2L);
        session.delete(user);
        tx.commit(); session.close();
    }

    // 修改 (持久態物件修改屬性 -> 提交事務自動同步)
    @Test public void update() {
        Session session = H3Util.getSessionFactory().openSession();
        Transaction tx = session.beginTransaction();
        User user = (User) session.get(User.class, 1L);
        user.setPassword("111111"); // 無需呼叫 update()
        tx.commit(); session.close();
    }

    // HQL 列表查詢
    @Test public void findList() {
        Session session = H3Util.getSessionFactory().openSession();
        List<User> list = session.createQuery("from User").list();
        session.close();
    }
}

三、Hibernate 三大物件狀態與轉換

狀態特徵典型操作
瞬時態 (Transient)new 出來、無 OID、不受 Session 管理session.save() → 持久態
持久態 (Persistent)有 OID、受 Session 管理、變更自動同步 DBsession.delete() → 遊離態 / session.evict() → 遊離態
遊離態 (Detached)有 OID、曾受管理、現不受 Session 管理session.update()/merge() → 持久態 / session.save() 拋異常 (OID 衝突)

狀態轉換實戰演示

@Test public void statusDemo() {
    Session session = sf.openSession(); Transaction tx = session.beginTransaction();

    // TO: 瞬時態
    User user = new User(null, "nnn", "123", new Date(), 0, 999f);
    session.save(user);  // TO → PO (賦予 OID)
    tx.commit();         // 同步到 DB
    // session.close();  // 若關閉 Session → DO (遊離態)

    // PO: 持久態 (修改屬性自動髒檢查)
    user.setUsername("wangwu"); // 無需 update()

    // DO: 遊離態 (session.close() 後)
    // session.update(user); // 重新關聯 → PO
    // session.delete(user); // PO → TO (刪除後變瞬時態)

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

四、一級緩存 (Session 級緩存) 深度解析

  • 作用範圍:單個 Session 內,生命週期與 Session 綁定。
  • 命中條件:session.get()、session.load()、session.byId() 依 ID 查詢;HQL/QBC/SQL 查詢不走一級緩存 (每次發 SQL)。
  • 髒檢查機制:事務提交前,Session 掃描所有持久態物件,比對快照,發送 UPDATE SQL。

驗證代碼

@Test public void testL1Cache() {
    Session session = sf.openSession();

    // 1. get 兩次同 ID → 只發 1 條 SQL
    User u1 = (User) session.get(User.class, 1L);
    User u2 = (User) session.get(User.class, 1L); // 命中緩存
    assertSame(u1, u2); // 同一物件引用

    // 2. HQL 查詢不走緩存
    Query q1 = session.createQuery("from User where id=1");
    Query q2 = session.createQuery("from User where id=1"); // 發 2 條 SQL

    // 3. 修改持久態物件,再次 get 看到最新值 (無 SQL)
    u1.setName("admin");
    User u3 = (User) session.get(User.class, 1L);
    assertEquals("admin", u3.getName());

    session.close();
}

五、查詢大全:HQL / QBC / 原生 SQL

1. HQL (Hibernate Query Language) - 面向物件

// 分頁
query.setFirstResult((pageNo-1)*pageSize).setMaxResults(pageSize);

// 命名/位置參數 (推薦命名參數)
query.setString("username", "%test%"); // like
query.setParameter("salary", 10000f);  // 類型不確定時

// 投影查詢 (選特定欄位)
List<Object[]> rows = session.createQuery("select u.id, u.name from User u").list();
List<User> users = session.createQuery("select new User(id, name) from User where id=:id").setLong("id", 1).list();

// 聚合函數
Long count = (Long) session.createQuery("select count(*) from User").uniqueResult();
Double avg = (Double) session.createQuery("select avg(salary) from User").uniqueResult();

// 分組
List<Object[]> groups = session.createQuery("select sex, count(*) from User group by sex").list();

// 排序
List<User> sorted = session.createQuery("from User order by salary desc, id asc").list();

// 命名查詢 (映射文件中定義)
Query nq = session.getNamedQuery("findOrder");

2. QBC (Query By Criteria) - 完全物件化、型別安全

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

// 條件
c.add(Restrictions.eq("username", "李四"));
c.add(Restrictions.like("username", "%test%"));
c.add(Restrictions.between("salary", 3000, 8000));
c.add(Restrictions.isNull("birthday"));

// 投影 (選欄位)
ProjectionList pl = Projections.projectionList()
    .add(Projections.property("username"))
    .add(Projections.property("sex"));
c.setProjection(pl);

// 分組
c.setProjection(Projections.projectionList()
    .add(Projections.groupProperty("sex"))
    .add(Projections.rowCount()));

// 分頁 & 排序
c.setFirstResult(0).setMaxResults(10)
 .addOrder(Order.asc("salary")).addOrder(Order.desc("id"));

3. 原生 SQL 查詢 - 繞過 Hibernate 方言、呼叫資料庫特有函數

// 1. 純標量查詢 (回傳 Object[])
SQLQuery sql = session.createSQLQuery("select * from t_user");
List<Object[]> rows = sql.list();

// 2. 自動映射實體 (addEntity)
sql.addEntity(User.class);
List<User> users = sql.list();

// 3. 別名映射 (多表連接時)
sql.addEntity("u", User.class); // select u.* from t_user u

六、最佳實踐總結

  1. 優先用 HQL/JPQL:可移植、面向物件、支援緩存。
  2. 動態條件用 QBC/CriteriaBuilder:型別安全、避免字串拼接 SQL 注入風險。
  3. 複雜報表/資料庫特有功能用原生 SQL:窗口函數、CTE、JSON 操作等。
  4. 善用一級緩存:同 Session 內多次 get/load 同 ID 無額外 SQL。
  5. 避免 N+1 問題:關聯查詢加 fetch="join" 或 HQL left join fetch。
  6. 大批量操作用 StatelessSession 或 JDBC 批次:繞過一級緩存與髒檢查,記憶體佔用極低。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved