休眠CriteriaAPI和类似操作。 交换操作数+数据库独立级联 - 这可能吗?(Hibern

2019-11-01 02:59发布

介绍

我有一个奇怪的任务 - 对Hibernate的标准API(即数据库独立的风格)SQL查询类似写

select * from branch b where '2/5/3/' like b.hier_path + '%' 

其中+是连接运算符。 置运算符取决于数据库“+”在MS SQL,“||” 在甲骨文等。

我必须使用标准的API(没办法切换到HQL)。

问题1 -像运营商

不幸的是,休眠允许只写基于Java对象的属性标准:

pCriteria.createCriteria(Branch.class).add(Restrictions.like("hierarchyPath", "2/5/3/%"));

这相当于中

select * from branch where 'hier_path like 2/5/3/%'

我不知道怎么样换运营商的操作数。

问题2 -独立于数据库级联

在SQL代码必须工作在Oracle,MS SQL服务器,DB2,Postgres的中,Sybase,MySQL和HSQLDB,火鸟(和其他一些新的关系型数据库)。

我已经得到了,现在是一个基于SQL黑客:

Restrictions.sqlRestriction("? like concat({alias}.hier_path,'%')", "2/5/3/", Hibernate.STRING)

不幸的是, concat是存在于大多数从上述数据库(除外的Postgres和火鸟) 数据库相关函数。 该方法是一种解决方法,不能(我会尝试添加自定义函数作为常数解决方案concat到没有它的数据库)。

结论

任何人可以提出一个改进我的黑客(数据库独立SQL)或修正原有CriteriaAPI?

更新12年9月28日

concat功能出现在9.1 Postgres的

Answer 1:

你可以写你自己的标准执行,这会产生类似于你在你的问题有一个SQL子句,除非它会使用与标准相关联的方言查询,以获得相应的concat函数,并委托级联到这个数据库依赖concat函数。



Answer 2:

由于@JB Nizet。 代码被他的思想的启发:

private class InverseLikeExpression extends SimpleExpression{
    private static final String CONST_HQL_FUNCTION_NAME_CONCAT = "concat";
    private static final String CONST_LIKE = " like ";
    private static final String CONST_LIKE_SUFFIX = "'%'";

    private final String propertyName;

    protected InverseLikeExpression(String pPropertyName, Object pValue) {
        super(pPropertyName, pValue, CONST_LIKE);
        propertyName = pPropertyName;
    }

    @Override
    public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
        String[] columns = criteriaQuery.getColumnsUsingProjection(criteria, propertyName);
        Dialect dialect = criteriaQuery.getFactory().getDialect();
        SQLFunction concatFunction = (SQLFunction) dialect.getFunctions().get(CONST_HQL_FUNCTION_NAME_CONCAT);

        StringBuffer fragment = new StringBuffer();
        if (columns.length>1) fragment.append('(');
        for ( int i=0; i<columns.length; i++ ) {
            String fieldName = concatFunction.render(Arrays.asList(new Object[] {columns[i], CONST_LIKE_SUFFIX}), criteriaQuery.getFactory());
            fragment.append("?").append( getOp() ).append(fieldName);
            if ( i<columns.length-1 ) fragment.append(" and ");
        }
        if (columns.length>1) fragment.append(')');
        return fragment.toString();
    }       
}


文章来源: Hibernate CriteriaAPI and like operator. Swap operands + database independent concatenation - is it possible?