0

イントロ

私には奇妙な仕事があります-HibernateCriteriaAPI(つまりデータベースに依存しないスタイル)で書くには、次のようなSQLクエリがあります

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

+連結演算子はどこにありますか。連結演算子は、MSSQLのデータベースに依存する'+'、'||' Oracleなどで。

Criteria APIを使用する必要があります(HQLに切り替える方法はありません)。

問題#1-演算子のような

残念ながら、HibernateではJavaオブジェクトのプロパティに基づいてCriteriaのみを書き込むことができます。

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

これは

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

like演算子のオペランドを入れ替える方法がわかりません。

問題#2-データベースに依存しない連結

SQLコードは、Oracle、MS SQL Server、DB2、Postgres、Sybase、MySQL、HSQLDB、Firebird(およびその他の新しいリレーショナルデータベース)で機能する必要があります。

私が今持っているのはSQLベースのハックです:

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

残念ながら、上記のデータベース(PostgresとFirebirdを除く)のほとんどに存在するデータベース依存concat関数です。このアプローチは回避策であり、一定の解決策として使用することはできません(カスタム関数を持たないデータベースに追加しようとします)。concat

結論

誰かが私のハック(データベースに依存しないSQL)の改善または元のCriteriaAPIの修正を提案できますか?

更新28.09.12

concat関数はPostgres9.1に表示されます

4

2 に答える 2

1

独自のCriterion実装を記述して、質問にあるものと同様のSQL句を生成できます。ただし、条件クエリに関連付けられた方言を使用して適切な連結関数を取得し、このデータベースに依存する連結を委任します。連結関数。

于 2012-09-28T12:02:02.003 に答える
0

@JBNizetに感謝します。彼のアイデアに触発されたコード:

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();
    }       
}
于 2012-09-28T16:18:33.577 に答える