首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計疑難解答

Hibernate Native SQL 優化 select *:改用 HQL 查詢實體或投影查詢

     編輯:程式設計疑難解答

問題背景

大量使用 session.createNativeQuery("SELECT * FROM table WHERE ..."),導致:

  • 獲取無用列,增加網絡 IO、內存佔用、反序列化開銷。
  • 無法利用 Hibernate 二級緩存/查詢緩存 (Native SQL 默認不走緩存)。
  • 實體映射脆弱:表結構變更 (增/刪列) 直接導致運行時錯誤。
  • 可移植性差:綁定特定數據庫方言。

方案一:HQL/JPQL 查詢實體 (最推薦、自動優化、緩存友好)


// 返回完整實體對象,Hibernate 自動生成 SELECT 列列表 (僅映射字段)
List list = session.createQuery("FROM Entity e WHERE e.condition = :cond", Entity.class)
                           .setParameter("cond", value)
                           .list();
// 生成 SQL: SELECT e.id, e.name, e.col1 ... FROM table e WHERE e.condition = ?
// 自動適配實體映射字段,表新增列不影響查詢

方案二:投影查詢 (只選需要的列、DTO 映射、性能最優)


// 1. 定義 DTO (構造函數或 @Data)
public class EntitySummaryDTO {
    private Long id;
    private String name;
    private BigDecimal price;
    // 構造函數/Getter/Setter
}

// 2. HQL 新對象查詢
List list = session.createQuery(
    "SELECT NEW com.dto.EntitySummaryDTO(e.id, e.name, e.price) " +
    "FROM Entity e WHERE e.status = 1", EntitySummaryDTO.class)
    .list();

// 3. 或 JPA Tuple/Object[]
List list = session.createQuery(
    "SELECT e.id, e.name, e.price FROM Entity e WHERE e.status = 1")
    .list();
// 手動映射: new EntitySummaryDTO((Long)arr[0], (String)arr[1], (BigDecimal)arr[2])

方案三:Native SQL + ResultTransformer 映射 DTO (不得已用 Native 時)


List list = session.createNativeQuery(
    "SELECT id, name, price FROM table WHERE status = 1") // 顯式列出列,不寫 *
    .setResultTransformer(Transformers.aliasToBean(EntitySummaryDTO.class))
    .list();

方案對比

方案性能緩存支持可移植性維護性適用場景
HQL 實體查詢良 (全列)✅ 二級/查詢緩存✅ 方言無關✅ 實體變更自適應**需完整實體、通用業務**
HQL 投影查詢 (DTO)**最優 (按需取列)**✅ 查詢緩存✅ 方言無關✅ DTO 穩定、實體變更不影響**列表/報表/只需部分字段**
Native SQL + ResultTransformer優 (按需取列)❌ 無緩存❌ 綁定方言⚠️ SQL 手寫維護極複雜 SQL/存儲過程/特定 DB 功能
Native SQL select *差 (全表掃描/全列傳輸)❌ 無緩存❌ 綁定方言❌ 表結構變更即崩**堅決杜絕**

治理策略:從根源杜絕 select *

  1. 代碼審查規則: SonarQube/Checkstyle 禁止 SELECT \* (正則 SELECT\s+\*)。
  2. 重構存量: 批量將 Native SQL 改為 HQL 實體查詢或投影查詢。**投影查詢 (DTO) 是性能與維護的最佳平衡點**。
  3. 實體定義完善: 所有表對應 Entity,字段用 @Column 顯式映射,新增字段默認不影響現有查詢。
  4. 統一 Repository/BaseDao 封裝: 封裝通用查詢方法 (如 findByCondition(cond, pageable)),業務代碼不直接寫 HQL/SQL。

總結

Hibernate Native SQL 優化 select *:徹底拋棄 select *,改用 HQL 實體查詢 (需全實體) 或投影查詢 DTO (只需部分字段、性能最優)。 Native SQL 僅作為最後手段 (複雜報表/存儲過程),且必須顯式列出列名 + ResultTransformer 映射 DTO。建立代碼審查機制從源頭杜絕 select *。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved