我正在使用Java,Eclipse和Spring开发应用程序。我们有一个要使用JDBC连接的Oracle数据库。
当前,应用程序正在使用应用程序中的临时查询到数据库。这些大多数都是在我来之前由从事该项目的人员完成的。我已经决定使用存储过程是一种更好的方法。解耦以获得另一层抽象。不必每次都发送sql语句,因此带宽更少,事务处理更快。 Oracle可以对它们进行优化,而不像传统的那样。只要输入和输出不变,就可以对它们进行更改,而无需重新编译。所有这些奇妙的东西。
adhoc查询经常返回多行,并使用rowMapper和mapRow接口
return jdbcTemplate.query(sql, new adhoc_mapper1());
class adhoc_mapper1 implements RowMapper<List<String>> {
public List<String> mapRow(ResultSet rs, int arg1) throws SQLException{
ArrayList<String> arr1 = new ArrayList<String>();
arr1.add(rs.getString("OUT_POSITION_ID"));
arr1.add(rs.getString("OUT_POSITION_TITLE_EN"));
return arr1;
}
}
春季临时查询
SELECT HR.POSITION_ID, HR.POSITION_TITLE_EN, HR.POSITION_TITLE_FR, HR.SECURITY_ID, HR.GROUP_NAME, HR.GROUP_LEVEL, HR.POSITION_IS_ACTIVE
FROM HR_POSITION HR JOIN DRILL_POSITION DP ON (HR.POSITION_ID = DP.POSITION_ID)
WHERE DP.TYPEVALUE = RECORD_TYPE;
Oracle中的被调用过程
CREATE OR REPLACE PROCEDURE DOCSADM.DRILL_RECORD_POSITION (
RECORD_TYPE IN VARCHAR2,
OUT_POSITION_ID OUT VARCHAR2,
OUT_POSITION_TITLE_EN OUT VARCHAR2,
OUT_POSITION_TITLE_FR OUT VARCHAR2,
OUT_SECURITY_ID OUT VARCHAR2,
OUT_GROUP_NAME OUT VARCHAR2,
OUT_GROUP_LEVEL OUT VARCHAR2,
OUT_POSITION_IS_ACTIVE OUT VARCHAR2
) AS
BEGIN
SELECT HR.POSITION_ID, HR.POSITION_TITLE_EN, HR.POSITION_TITLE_FR, HR.SECURITY_ID, HR.GROUP_NAME, HR.GROUP_LEVEL, HR.POSITION_IS_ACTIVE
INTO OUT_POSITION_ID, OUT_POSITION_TITLE_EN, OUT_POSITION_TITLE_FR, OUT_SECURITY_ID, OUT_GROUP_NAME, OUT_GROUP_LEVEL, OUT_POSITION_IS_ACTIVE
FROM HR_POSITION HR JOIN DRILL_POSITION DP ON (HR.POSITION_ID = DP.POSITION_ID) WHERE DP.TYPEVALUE = RECORD_TYPE;
END DRILL_RECORD_POSITION;
如您所见,该过程返回多行。我曾问过question关于如何在Oracle中查看该过程的输出的信息,但是没有成功。
由于该项目未使用被调用的过程,因此我在代码库中没有可用于工作的示例。我的一个参与另一个项目的同事使用了它们,并且很友好地向我展示了他们的示例,但遗憾的是,这没有帮助,因为它仅调用一个过程且没有任何回报。他们的整体设计也似乎有所不同。但是我看到他们正在使用SimpleJdbcCall,所以我开始在网上寻找使用它的方法。
网上的好例子,我没能上班。
我发现一些例子正在做我需要做的事情,但并不完全符合我的期望。
我不想为每个过程或过程系列创建一个类。大多数查询最终都会在表中显示信息,因此我一直在使用2d对象来保存然后显示数据。到目前为止非常方便。我可以为每个过程创建一个映射,因为它需要完成(除非有更好的方法?),但是我不想为每个过程(有时也包括映射器)创建一个类。
我有150行失败的代码尝试,为了使问题更短,我没有列出。如果他们有帮助,那么我可以包括他们。
TL; DR 我想从Spring调用Oracle中的存储过程,该存储过程将返回多行。我只想使用调用函数,该函数要么使用RowMapper的映射方法,要么使用in函数映射。如果可能,我想避免使用数据的类结构。我希望/希望它看起来像第一个代码块一样被使用。
答案 0 :(得分:0)
我的方法存在一个基本错误。我尝试返回多行的方式是错误的。正如某人在我的链接问题中指出的那样。因此,我尝试访问它的方式也是错误的。当我将返回限制为一行时,以下操作成功。
首先进口
import java.sql.Connection;
import java.sql.CallableStatement;
然后打电话
final String procedureCall = "{call DRILL_RECORD_POSITION(?, ?, ?, ?, ?, ?, ?, ?)}";
try (Connection connection = jdbcTemplate.getDataSource().getConnection();)
{
ArrayList<String> inner = new ArrayList<String>();
CallableStatement callableSt = connection.prepareCall(procedureCall);
callableSt.setString(1, "D");
callableSt.registerOutParameter(2, Types.VARCHAR);
callableSt.registerOutParameter(3, Types.VARCHAR);
callableSt.registerOutParameter(4, Types.VARCHAR);
callableSt.registerOutParameter(5, Types.VARCHAR);
callableSt.registerOutParameter(6, Types.VARCHAR);
callableSt.registerOutParameter(7, Types.VARCHAR);
callableSt.registerOutParameter(8, Types.VARCHAR);
//Call Stored Procedure
callableSt.executeUpdate();
for (int i=2; i<9; i++)
{
System.out.println(callableSt.getString(i));
}
}catch (SQLException e) {
e.printStackTrace();
}
请注意,我正在尝试使用资源,因此不必担心关闭连接。
在此期间我犯的其他错误还不够?在字符串中导致无效的列索引错误。然后我犯了一个错误,那就是在我实际执行呼叫之前尝试获取信息。