一、先创建一个存储过程
CREATE DEFINER=`root`@`localhost` PROCEDURE `proc_adder`(IN `a` int,IN `b` int,OUT `sum` int) BEGIN if a is null then set a = 0; end if; if b is null then set b = 0; end if; set sum = a + b; END
存储过程proc_adder功能很简单,两个整型输入参数a和b,一个整型输出参数sum,功能就是计算输入参数a和b相加的结果,赋值给输出参数sum;
在SQL中调用存储过程
set @b=5; call proc_adder(2,@b,@s); select @s as sum;
结果如下:
二、使用JdbcTemplate调用存储过程
JdbcTemplate在 spring-jdbc-5.0.2.RELEASE.jar 中,我们在导包的时候,除了要导入这个 jar 包外,还需要导入一个 spring-tx-5.0.2.RELEASE.jar(它是和事务相关的)。
引入依赖:
<!-- jdbcTemplate -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
使用时直接注入即可
@Autowired private JdbcTemplate jdbcTemplate;
代码:
@RunWith(SpringRunner.class) @SpringBootTest(classes = PtsServerApplication.class) @Slf4j public class TestDemo { @Autowired private JdbcTemplate jdbcTemplate; @Test public void test() { final int[] sum = new int[1]; jdbcTemplate.execute(new ConnectionCallback() { @Override public Object doInConnection(Connection connection) throws SQLException, DataAccessException { //不自动提交,即为手动提交 connection.setAutoCommit(false); //预处理,指定存储过程名和参数,?作为占位符,后面根据占位符赋值或设置输出值的类型 CallableStatement statement = connection.prepareCall("{ call proc_adder(2,?,?)}"); // 给存储过程中的输入参数赋值, statement.setInt(1, 5); // 存储过程中的输出参数处理方式 statement.registerOutParameter(2, Types.INTEGER); statement.execute(); //获取返回的参数 sum[0] = statement.getInt(2); connection.commit(); return null; } }); log.info("返回的参数:{}", sum[0]); System.out.println(sum[0]); } }
使用jdbcTemplate方式时,必须要设置不自动提交。另外调用时的参数必须对应,即使是输出参数也要指定占位符,设置输出的类型。
三、通过Mybatis调用mysql存储过程
TestMaper.xml
方式一:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.ljxx.dao.TestDao"> <select id="call" statementType="CALLABLE"> {call proc_adder(2, #{b,mode=IN,jdbcType=INTEGER}, #{sum,mode=OUT,jdbcType=INTEGER} ) } </select> </mapper>
指定参数名,出入参类型及参数对应数据库的数据类型。
方式二、使用占位符方法
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.ljxx.dao.TestDao"> <select id="call" statementType="CALLABLE" parameterMap="AddrMap"> {call proc_adder(2,?,?)} </select> <!--定义参数--> <parameterMap id="AddrMap" type="java.util.Map"> <parameter property="b" jdbcType="INTEGER" mode="IN" /> <parameter property="sum" jdbcType="INTEGER" mode="OUT" /> </parameterMap> </mapper>
TestDao
public interface TestDao { void call(Map<String, Object> map); }
调用TestDao接口
@RunWith(SpringRunner.class) @SpringBootTest(classes = PtsServerApplication.class) @Slf4j public class TestDemo { @Autowired private TestDao testDao; @Test public void test1() { Integer b = 5; Map<String, Object> map = new HashMap<>(); map.put("b",b); testDao.call(map); int sum = 0; if (map != null && map.get("sum") != null) { sum = (Integer) map.get("sum"); } log.info("返回的参数:{}", sum); System.out.println(sum); } }
参数需要使用map进行定义,其中输入参数需事先定义,输出参数在调用后直接从map中获取即可,无需对方法写返回值。
注意:
(1)上面两种方法在xml中必须指定statementType="CALLABLE",否则会报错。
(2)jdbcType是mysql数据库的类型,不是java的基本类型