关于jdbc取存储过程和函数的问题

jdbc连接后得到连接connection,然后获取metadata,利用jdbc从数据库中取存储过程和函数

    ... ... ... ...
Connection connection = DriverManager.getConnection(URL,USERNAME,PASSWORD);
Database database = connection.getMetaData();

//获取数据库信息
//System.out.println(conn.getCatalog());
//System.out.println(database.getDriverName());
//System.out.println(database.getDriverVersion());
//System.out.println(database.getDatabaseProductName());
//System.out.println(database.getDatabaseProductVersion());

//存储过程
ResultSet result = database.getProcedures("表名",null,"%");
//函数
//ResultSet result = database.getFunctions("表名",null,"%");

//打印存储过程/函数
while (result.next()){
    for (int i = 1; i <= columnsNumber; i++) {
        String columnValue = result.getString(i);
        System.out.println(resultData.getColumnName(i)+" 列: "+columnValue+" , ");
    }
    System.out.println("------------------------------");
}

connection.close();
    ... ... ... ...

然后发现jdbc取出来的存储过程和函数是重合的。

在sqlserver中,无论是getProcedures还是getFunctions方法,都会把存储过程和函数都取出来,而且getProcedures取出来的函数列名都为" * procedure * ",getFunctions则是相反。

在mysql中,getProcedures会将存储过程和函数都取出来,结果和sqlserver中一样。但是mysql中getFunctions取出来的函数又仅仅只有函数,不会连同存储函数一起取出来。

oracle同理,其余数据库还未去看。

光从jdbc取出来的数据来看很难完全区分开存储过程和函数,也不能从返回结果区分,返回结果的枚举类有三种,还有ResultUnknown。

百度了一天也没有找到合适的区分方法,大多都是讲的理论上存储过程和函数的区别,不曾提到jdbc取出来的差异,我个人觉得是因为两者很相似,导致了这种结果。在jdbc的metadata实现类里,sqlserver等数据库驱动jar包里的不明显(说是不明显,其实是我能力薄弱有点没看懂,所以换个数据库的举例子),但mysql驱动jar包中的metadata实现类里就是很明显的getProcedures方法里会取函数。

//驱动 com.mysql.cj.jdbc.Driver

package com.mysql.cj.jdbc;

public class DatabaseMetaData implements java.sql.DatabaseMetaData {
    ... ... ... ...
    ... ... ... ...
    //getProcedures方法
    public ResultSet getProcedures(String catalog, String schemaPattern, String     procedureNamePattern) throws SQLException {
        try {
            return this.getProceduresAndOrFunctions(this.createFieldMetadataForGetProcedures(), catalog, schemaPattern, procedureNamePattern, true, (Boolean)this.conn.getPropertySet().getBooleanProperty(PropertyKey.getProceduresReturnsFunctions).getValue());
        } catch (CJException var5) {
            throw SQLExceptionsMapping.translateException(var5, this.getExceptionInterceptor());
        }
    }

    // getProcedures 以及 getFunctions 后续调用的方法
    protected ResultSet getProceduresAndOrFunctions(final Field[] fields, String catalog, String schemaPattern, final String procedureNamePattern, final boolean returnProcedures, final boolean returnFunctions) throws SQLException {
    ... ... ... ...
    ... ... ... ...
}

    //getFunctions方法
    public ResultSet getFunctions(String catalog, String schemaPattern, String functionNamePattern) throws SQLException {
        try {
            return this.getProceduresAndOrFunctions(this.getFunctionsFields(), catalog, schemaPattern, functionNamePattern, false, true);
        } catch (CJException var5) {
            throw SQLExceptionsMapping.translateException(var5, this.getExceptionInterceptor());
        }
    }

其中涉及到一个返回Boolean类型的判断,这个true or false就决定了取存储过程时候返不返回函数,暂时没能理解是怎么进行判断的,只是实际使用时基本就是true导致存储过程和函数一起返回。而mysql驱动中的getFuntions方法,就是直接调方法时传入procedures为false,functions为true,所以调用方法只返查出了函数,符合需求。

对了,sqlserver中虽然两个方法都会全部取出来,但是存储过程名的列下的结构为[存储过程的名字,1],函数名的列下为[函数的名字,0]。目前暂时不知道这个1和0是不是存储过程和函数的标识,不过就算是也不好在项目中区分。而且全取出来再去区分其实也有点像是画了一条有脚的蛇,然后再去把脚剁掉。

最后实在没有什么好办法,jdbc用不了,只能划分数据库区分存储过程和函数。直接区分不同的数据库实现类,写了sql语句,执行相应的sql语句把存储过程和函数分别取出来。

接口为

/**
 * 数据库类型接口,区分数据库执行查询存储过程和函数
 *
 * @author QiaoQiao
 * @since ******
 */
public interface DatabaseType {
    /**
     * 查询存储过程
     * @param ******* 数据库服务
     * @return List<procedure>
     */
    Object procedure(传入接口中自动装载的数据库服务作为参数);

    /**
     * 查询存储函数
     * @param ******* 数据库服务
     * @return List<function>
     */
    Object function(传入接口中自动装载的数据库服务作为参数);

    /**
     * 获取数据库类型;
     * <p>
     * 由一个DatabaseTypeImplFactory工厂类根据当前项目使用的数据库类型获取相应的实现类,
     * 执行对应的sql取存储过程或者函数.
     * @return database#type/name
     */
    String getDatabaseType();
}

虽然法子笨了点,并且不能无视数据库差异,加一种数据库就得多个实现类,不过总体逻辑是差不多的,起码sqlserver,mysql,oracle三种数据库差不多,就差个sql语句,结果集是类似的,同种方法解析即可,返回的是存储过程或者函数的名字以及对应的参数的列表。

如果后面能找到jdbc方法中如何单独查询出存储过程或者函数的法子就更好了。

萌新一只,基础略差,如有不对请多指教!加油加油加油!冲呀!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值