Jpa 重寫方言dialect 使用oracle / mysql 數據庫自定義函數


在使用criteria api進行查詢時 criteriaBuilder只提供了一個部分標准的sql函數,但當我們需要使用oracle特有的行轉列函數wm_concat或

mysql特有的行轉列函數group_concat時,就只能自己封裝了,

criteriaBuilder提供了一個封裝函數的方法:

    /**
     * Create an expression for the execution of a database
     * function.
     * @param name  function name
     * @param type  expected result type
     * @param args  function arguments
     * @return expression
     */
   <T> Expression<T> function(String name, Class<T> type,
Expression<?>... args);

如我們封裝wm_concat函數,代碼如下:

Expression<String> wmConcat = cb.function("wm_concat",
                String.class, root.get("ID"));

生成的sql 如:select  wm_concat(id)........

如果我們想生成 select wm_concat(distinct(id))這個的形式,來去id進行去重distinct。可以用下面的代碼,對function進行嵌套:

        Expression<String> distinct = cb.function("distinct",
                String.class, root.get("ID"));

        Expression<String> wmConcat = cb.function("wm_concat",
                String.class, distinct);

當然這還沒有完,生成這樣的函數后,其實jpa是不認可wm_concat函數的,(distinct函數,lower函數等是認可的),這是為什么呢,因為jpa認可的oracle函數都會在OracleDialect定義。

如我使用的OracleDialect版本是Oracle12cDialect,它本身沒有注冊自定義函數,但是它繼承的類Oracle8iDialect注冊了很多函數,如下:

protected void registerFunctions() {
        registerFunction( "abs", new StandardSQLFunction("abs") );
        registerFunction( "sign", new StandardSQLFunction("sign", StandardBasicTypes.INTEGER) );

        registerFunction( "acos", new StandardSQLFunction("acos", StandardBasicTypes.DOUBLE) );
        registerFunction( "asin", new StandardSQLFunction("asin", StandardBasicTypes.DOUBLE) );
        registerFunction( "atan", new StandardSQLFunction("atan", StandardBasicTypes.DOUBLE) );
        registerFunction( "bitand", new StandardSQLFunction("bitand") );
        registerFunction( "cos", new StandardSQLFunction("cos", StandardBasicTypes.DOUBLE) );
        registerFunction( "cosh", new StandardSQLFunction("cosh", StandardBasicTypes.DOUBLE) );
        registerFunction( "exp", new StandardSQLFunction("exp", StandardBasicTypes.DOUBLE) );
        registerFunction( "ln", new StandardSQLFunction("ln", StandardBasicTypes.DOUBLE) );
        registerFunction( "sin", new StandardSQLFunction("sin", StandardBasicTypes.DOUBLE) );
        registerFunction( "sinh", new StandardSQLFunction("sinh", StandardBasicTypes.DOUBLE) );
        registerFunction( "stddev", new StandardSQLFunction("stddev", StandardBasicTypes.DOUBLE) );
        registerFunction( "sqrt", new StandardSQLFunction("sqrt", StandardBasicTypes.DOUBLE) );
        registerFunction( "tan", new StandardSQLFunction("tan", StandardBasicTypes.DOUBLE) );
        registerFunction( "tanh", new StandardSQLFunction("tanh", StandardBasicTypes.DOUBLE) );
        registerFunction( "variance", new StandardSQLFunction("variance", StandardBasicTypes.DOUBLE) );

        registerFunction( "round", new StandardSQLFunction("round") );
        registerFunction( "trunc", new StandardSQLFunction("trunc") );
        registerFunction( "ceil", new StandardSQLFunction("ceil") );
        registerFunction( "floor", new StandardSQLFunction("floor") );

        registerFunction( "chr", new StandardSQLFunction("chr", StandardBasicTypes.CHARACTER) );
        registerFunction( "initcap", new StandardSQLFunction("initcap") );
        registerFunction( "lower", new StandardSQLFunction("lower") );
        registerFunction( "ltrim", new StandardSQLFunction("ltrim") );
        registerFunction( "rtrim", new StandardSQLFunction("rtrim") );
        registerFunction( "soundex", new StandardSQLFunction("soundex") );
        registerFunction( "upper", new StandardSQLFunction("upper") );
        registerFunction( "ascii", new StandardSQLFunction("ascii", StandardBasicTypes.INTEGER) );

        registerFunction( "to_char", new StandardSQLFunction("to_char", StandardBasicTypes.STRING) );
        registerFunction( "to_date", new StandardSQLFunction("to_date", StandardBasicTypes.TIMESTAMP) );

        registerFunction( "current_date", new NoArgSQLFunction("current_date", StandardBasicTypes.DATE, false) );
        registerFunction( "current_time", new NoArgSQLFunction("current_timestamp", StandardBasicTypes.TIME, false) );
        registerFunction( "current_timestamp", new NoArgSQLFunction("current_timestamp", StandardBasicTypes.TIMESTAMP, false) );

        registerFunction( "last_day", new StandardSQLFunction("last_day", StandardBasicTypes.DATE) );
        registerFunction( "sysdate", new NoArgSQLFunction("sysdate", StandardBasicTypes.DATE, false) );
        registerFunction( "systimestamp", new NoArgSQLFunction("systimestamp", StandardBasicTypes.TIMESTAMP, false) );
        registerFunction( "uid", new NoArgSQLFunction("uid", StandardBasicTypes.INTEGER, false) );
        registerFunction( "user", new NoArgSQLFunction("user", StandardBasicTypes.STRING, false) );

        registerFunction( "rowid", new NoArgSQLFunction("rowid", StandardBasicTypes.LONG, false) );
        registerFunction( "rownum", new NoArgSQLFunction("rownum", StandardBasicTypes.LONG, false) );

        // Multi-param string dialect functions...
        registerFunction( "concat", new VarArgsSQLFunction(StandardBasicTypes.STRING, "", "||", "") );
        registerFunction( "instr", new StandardSQLFunction("instr", StandardBasicTypes.INTEGER) );
        registerFunction( "instrb", new StandardSQLFunction("instrb", StandardBasicTypes.INTEGER) );
        registerFunction( "lpad", new StandardSQLFunction("lpad", StandardBasicTypes.STRING) );
        registerFunction( "replace", new StandardSQLFunction("replace", StandardBasicTypes.STRING) );
        registerFunction( "rpad", new StandardSQLFunction("rpad", StandardBasicTypes.STRING) );
        registerFunction( "substr", new StandardSQLFunction("substr", StandardBasicTypes.STRING) );
        registerFunction( "substrb", new StandardSQLFunction("substrb", StandardBasicTypes.STRING) );
        registerFunction( "translate", new StandardSQLFunction("translate", StandardBasicTypes.STRING) );

        registerFunction( "substring", new StandardSQLFunction( "substr", StandardBasicTypes.STRING ) );
        registerFunction( "locate", new SQLFunctionTemplate( StandardBasicTypes.INTEGER, "instr(?2,?1)" ) );
        registerFunction( "bit_length", new SQLFunctionTemplate( StandardBasicTypes.INTEGER, "vsize(?1)*8" ) );
        registerFunction( "coalesce", new NvlFunction() );

        // Multi-param numeric dialect functions...
        registerFunction( "atan2", new StandardSQLFunction("atan2", StandardBasicTypes.FLOAT) );
        registerFunction( "log", new StandardSQLFunction("log", StandardBasicTypes.INTEGER) );
        registerFunction( "mod", new StandardSQLFunction("mod", StandardBasicTypes.INTEGER) );
        registerFunction( "nvl", new StandardSQLFunction("nvl") );
        registerFunction( "nvl2", new StandardSQLFunction("nvl2") );
        registerFunction( "power", new StandardSQLFunction("power", StandardBasicTypes.FLOAT) );

        // Multi-param date dialect functions...
        registerFunction( "add_months", new StandardSQLFunction("add_months", StandardBasicTypes.DATE) );
        registerFunction( "months_between", new StandardSQLFunction("months_between", StandardBasicTypes.FLOAT) );
        registerFunction( "next_day", new StandardSQLFunction("next_day", StandardBasicTypes.DATE) );

        registerFunction( "str", new StandardSQLFunction("to_char", StandardBasicTypes.STRING) );
    }

通過調試代碼,可以看到oracledialect共注冊了80個函數。

同理,我們也可繼承Oracle12cDialect,添加自己的函數:

public class MyOracleDialect extends Oracle12cDialect {

    /**
     * 添加oracler內置函數和自定義函數
     */
    @Override
    protected void registerFunctions() {
        super.registerFunctions();
        registerFunction("wm_concat", new StandardSQLFunction("wm_concat", StandardBasicTypes.STRING));
    }

    /**
     * 解決啟動時數字溢出的錯誤
     * @return
     */
    @Override
    public String getQuerySequencesString() {
        return "select * from user_sequences";
    }
}

配置完成后,啟動項目即可。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM