ValueList 框架中,queryMap 傳遞的參數默認皆為 String 類型。HQL 中直接賦值給整型字段會報類型不匹配錯誤。常見繞過方式是在 HQL 寫 to_number({param}),但此法存在遷移不兼容、維護成本高等問題。本文介紹通過 StatementBuilder 註冊 IntegerSetter 實現自動類型轉換。
<property name="hql">
<value>
FROM TBaseAreas tb
WHERE tb.status='1'
/~hId : AND tb.hId = to_number{hId} ~/
/~oId : AND tb.oId = to_number{oId} ~/
</value>
</property>
痛點:每個整型參數都需手寫轉型函數,跨數據庫遷移時函數名不同(Oracle TO_NUMBER、MySQL CAST、PostgreSQL ::int)。
<bean id="integerSetterHql" class="net.mlw.vlh.adapter.hibernate3.util.setter.IntegerSetter"/>
<bean id="statementBuilderHql" class="net.mlw.vlh.adapter.hibernate3.util.StatementBuilder">
<property name="setters">
<map>
<entry key="uId"><ref bean="integerSetterHql"/></entry>
<entry key="oId"><ref bean="integerSetterHql"/></entry>
<!-- 批量註冊所有整型參數 -->
</map>
</property>
</bean>
~hId : ... ~)StatementBuilder 遍歷 setters MapSetter.setValue() 進行類型轉換IntegerSetter 內部執行 Integer.valueOf(stringVal),再綁定為 JDBC Types.INTEGERpublic class BigDecimalSetter implements Setter {
public void setValue(Query query, String paramName, Object value) {
query.setBigDecimal(paramName, new BigDecimal((String) value));
}
}
<bean id="bigDecimalSetter" class="com.example.BigDecimalSetter"/>
<entry key="amount"><ref bean="bigDecimalSetter"/></entry>
| 維度 | HQL 手寫 to_number | Setter 自動轉換 |
|---|---|---|
| 遷移兼容性 | 差(函數名綁定具體方言) | 優(框架層面統一處理) |
| 維護成本 | 高(每處參數重複寫) | 低(集中配置一次) |
| 類型安全 | 運行時發現 | 綁定時強類型檢查 |
| 可讀性 | HQL 混雜轉型噪音 | HQL 純淨業務邏輯 |
集中配置類型轉換器,讓 HQL 回歸純業務表達,是框架正確使用姿勢。