使用场景:spring JDBC组件一般用于存储过程的调用,mybatis一般用于SQL语句的执行,不常用于调用存储过程。
1.使用spring的jdbcTemplate调用存储过程
核心思路:使用spring的JDBC组件,调用以下几个类
org.springframework.jdbc.core.JdbcTemplate;
org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
org.springframework.jdbc.core.namedparam.SqlParameterSource;
org.springframework.jdbc.core.simple.SimpleJdbcCall;
org.springframework.jdbc.datasource.DataSourceUtils;
代码如下:
SimpleJdbcCall simpleJdbcCall = new SimpleJdbcCall(this.jdbcTemplate.getDataSource());
simpleJdbcCall.withCatalogName("包名package").withProcedureName("过程名procedure");
SqlParameterSource parameterSource = new MapSqlParameterSource().addValues(map);
out = simpleJdbcCall.execute(parameterSource);
2.使用spring的jdbcTemplate执行SQL语句出错(ORA-00911)
Caused by: java.sql.SQLSyntaxErrorException: ORA-00911: 无效字符
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:439
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:395) at oracle.jdbc.driver.T4C8Oall.processError(T4C8Oall.java:802)
at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:436)
at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:186)
at oracle.jdbc.driver.T4C8Oall.doOALL(T4C8Oall.java:521)
at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:205)
at oracle.jdbc.driver.T4CPreparedStatement.executeForDescribe(T4CPreparedStatement.java:861)
at oracle.jdbc.driver.OracleStatement.executeMaybeDescribe(OracleStatement.java:1145)
at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1267)
at oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:3449)
at oracle.jdbc.driver.OraclePreparedStatement.executeQuery(OraclePreparedStatement.java:3493)
at oracle.jdbc.driver.OraclePreparedStatementWrapper.executeQuery(OraclePreparedStatementWrapper.java:1491)
at org.apache.commons.dbcp.DelegatingPreparedStatement.executeQuery(DelegatingPreparedStatement.java:93)
at org.springframework.jdbc.core.JdbcTemplate$1.doInPreparedStatement(JdbcTemplate.java:703)
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:644) ... 34 more
以上报错, 在plsql developer执行是没有错误的,但是写在java里面就报错。原来是因为 sql 语句中 多了冒号( ; ). 将java里面的sql语句中, 去掉冒号即可
3.spring的JDBC组件是否会自动提交事务
答案是:会!!!
public void test() throws Exception{
SimpleJdbcCall simpleJdbcCall = new SimpleJdbcCall(this.jdbcTemplate.getDataSource());
simpleJdbcCall.withCatalogName("pkg_test_temp").withProcedureName("get_testxx");
Map<String,String> map = new HashMap<String,String>();
map.put("pi_param", "hello");
SqlParameterSource parameterSource = new MapSqlParameterSource().addValues(map);
Map<String, Object> out = simpleJdbcCall.execute(parameterSource);
throw new Exception("测试springJDBC是否会回滚事务");
}
CREATE OR REPLACE PACKAGE BODY pkg_test_temp AS
PROCEDURE get_testxx(pi_param IN VARCHAR2,po_fhz OUT VARCHAR2,po_msg OUT VARCHAR2)
IS
v_max INT;
v_content varchar2(200);
BEGIN
BEGIN
SELECT MAX(pid)
INTO v_max
FROM temp_test_20200821;
EXCEPTION
WHEN OTHERS THEN
po_fhz := 'ECOMM000002';
po_msg := '获取最大值有误';
RETURN;
END;
v_content := '随便玩玩'||(v_max+1);
INSERT INTO temp_test_20200821(PID,CONTENT) VALUES(v_max+1,v_content);
po_fhz := '1';
po_msg := '调用成功'||pi_param;
EXCEPTION
WHEN OTHERS THEN
po_fhz := 'ECOMM000001';
po_msg := '调用存储过程:'||'pkg_test_temp'||'发生错误';
RETURN;
END get_testxx;
END pkg_test_temp;
/
show err
执行前数据库表记录 :
1 哈哈
执行后数据库表记录 :
1 哈哈
2 随便玩玩2
结论:springJDBC在执行完存储过程以后,便会自动提交事务,即便后面程序出现异常,数据依然修改成功(按设计要求,程序报错,数据是不允许修改成功的)这时就需要spring的事务管理来解决这个问题了,请看下一章
:spring AOP基于XML声明式事务管理的简单应用