大量使用 session.createNativeQuery("SELECT * FROM table WHERE ..."),導致:
// 返回完整實體對象,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 = ?
// 自動適配實體映射字段,表新增列不影響查詢
// 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 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 \* (正則 SELECT\s+\*)。@Column 顯式映射,新增字段默認不影響現有查詢。findByCondition(cond, pageable)),業務代碼不直接寫 HQL/SQL。Hibernate Native SQL 優化 select *:徹底拋棄 select *,改用 HQL 實體查詢 (需全實體) 或投影查詢 DTO (只需部分字段、性能最優)。 Native SQL 僅作為最後手段 (複雜報表/存儲過程),且必須顯式列出列名 + ResultTransformer 映射 DTO。建立代碼審查機制從源頭杜絕 select *。