Hibernate 中 formula属性的好用处在于 无需在数据库有真实的列 只需要写出sql 就可以创建一个虚拟的列 然后在 Dao层的查询中使用 ,比如在表 M_Confirmation 中有两列 Confirmation_Cost 和 Confirmation_Fee 这两列都容许包含null, 我们的query要求取得 Confirmation_Cost 和 Confirmation_Fee的和(暂时命名为Total_Price) 并查出此Total_Price>= 某个前台传进来的某个filter的数据 。
写成sql 就是 select (confirmation_cost + confirmation+fee) from m_confirmation where (confirmation_cost + confirmation+fee) >= ? ;
这时候创建虚拟列 ,formula后面的部分 会自动跟在hibernate发出的sql中 select后面作为一列 就好比 select formula from M_confirmation:
<property name="totalPrice" formula="((CASE WHEN Confirmation_Cost IS NULL THEN 0 ELSE Confirmation_Cost END) + (CASE WHEN Confirmation_Fee IS NULL THEN 0 ELSE Confirmation_Fee END))" />
注意:数据库中任何数+null都是null,所以必须用case when处理, 不能 用 nvl因为 nvl只能用于oracle 不符合hibernate移植到任何数据库的思想。
然后在 持久化对象中 写好对应的 totalPrice 属相:
public class Confirmation extends ConfirmationBase implements BasicModel { private BigDecimal totalPrice; public BigDecimal getTotalPrice() { return totalPrice; } public void setTotalPrice(BigDecimal totalPrice) { this.totalPrice = totalPrice; } @Override public String toString() { return ToStringBuilder.reflectionToString(this, TafToStringStyles.PERSISTENCE_TOSTRING_STYLE); }
这样 你就可以灵活使用数据库中任何列 排列组合成一些虚拟列 来做查询了:
BigDecimal bpsPrice = filter.getBpsPrice(); DetachedCriteria criteria = DetachedCriteria.forClass(Confirmation.class); if (bpsPrice != null) { criteria.add(Restrictions.ge("totalPrice", bpsPrice)); } return getHibernateTemplate().findByCriteria(criteria);
这就是属性中 formula属性的用处,最后再提醒一下 formula=配置的内容会自动跟在发出的sql的 select后面作为一列 ,所以很多人 后面写出完整的 select 最后拼出的sql是错误的。这样工作中方便更加区分逻辑 加快代码可读性 对数据库列的数量也没有太多影响,
当然你也可以在 Criteria中直接写 如下:
BigDecimal bpsPrice = filter.getBpsPrice(); DetachedCriteria criteria = DetachedCriteria.forClass(Confirmation.class); if (bpsPrice != null) { criteria .add(Restrictions.sqlRestriction("((CASE WHEN Confirmation_Cost IS NULL THEN 0 ELSE Confirmation_Cost END) + (CASE WHEN Confirmation_Fee IS NULL THEN 0 ELSE Confirmation_Fee END)) >=") + bpsPrice ); } return getHibernateTemplate().findByCriteria(criteria);
但是这样的写法严格的公司无法通过代码审核,因为不方便阅读 没有做到好的分层 假设新来的程序员如果改了表的列名而没有看到你写的这句会出现bug 一般这样写会被打回来从新改
如果你公司普遍使用Native sql 或者 HQL来做查询的标准 那这种formula配置就失去作用 没有用处了 完全可以用一些常量替代