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方法中如何单独查询出存储过程或者函数的法子就更好了。
萌新一只,基础略差,如有不对请多指教!加油加油加油!冲呀!