前言
存储过程是一组通过预先编译好的SQL语句,存储在数据库服务器中,被视作是可以执行的单个调用的执行单元,它允许将一系列SQL语句打包成一个逻辑单元,这样可以在需要的时候直接来调用这个逻辑单元来实现相关的操作。在一个存储过程中可以包括常用的复杂数据处理、业务逻辑操作等。
下面我们就来看看如何在Spring Boot中整合MyBatis调用存储过程实现。
存储过程的结构
sql
CREATE PROCEDURE procedure_name(parameters)
BEGIN
-- SQL statements
END;
其中,参数说明情况如下。
- procedure_name:存储过程的名称。
- parameters:存储过程的参数(可选)。
拿一个最经典的场景,来进行说明,例如有一个表格employees,包含员工的姓名和薪水。我们想要创建一个存储过程,根据员工的姓名增加或减少其薪水。可以通过如下的存储过程来实现。
sql
DELIMITER //
CREATE PROCEDURE update_salary(IN emp_name VARCHAR(50), IN salary_change DECIMAL(10, 2))
BEGIN
UPDATE employees
SET salary = salary + salary_change
WHERE name = emp_name;
END //
DELIMITER ;
上面我们创建了一个名为update_salary 的存储过程,并且这个存储过程接受了两个参数,员工的姓名(emp_name )和薪水变动的数值(salary_change)。
整个的存储过程包含了一个SQL语句,这个SQL语句就是用来更新员工薪水的SQL语句。要调用存储过程,可以使用 CALL 关键字来执行调用,如下所示。
arduino
CALL update_salary('John Doe', 500.00);
这个操作就会为 "John Doe" 的员工的薪水500美元。
使用MyBatis 调用存储过程?
假设我们定义了一个存储过程,用来获取员工信息,并且其会接收一个员工ID的参数作为传入的参数,并且会返回该员工的姓名和薪水,如下所示。
sql
CREATE PROCEDURE get_employee_info(
IN employeeId INT,
OUT name VARCHAR(50),
OUT salary DECIMAL(10, 2)
)
BEGIN
SELECT name, salary INTO name, salary
FROM employees
WHERE id = employeeId;
END;
接下来我们就需要定义一个Mapper的接口用来调用这个存储过程。如下所示。
less
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.math.BigDecimal;
@Mapper
public interface EmployeeMapper {
void getEmployeeInfo(@Param("employeeId") int employeeId, @Param("name") String name, @Param("salary") BigDecimal salary);
}
接口定义好之后接下来需要做的事情就是编写XML映射文件,如下所示。
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.example.mapper.EmployeeMapper">
<select id="getEmployeeInfo" statementType="CALLABLE">
{call get_employee_info(#{employeeId, mode=IN, jdbcType=INTEGER}, #{name, mode=OUT, jdbcType=VARCHAR}, #{salary, mode=OUT, jdbcType=DECIMAL})}
</select>
</mapper>
调用存储过程的代码实现
java
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
public class Main {
public static void main(String[] args) {
String resource = "mybatis-config.xml";
try (InputStream inputStream = Resources.getResourceAsStream(resource)) {
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
EmployeeMapper employeeMapper = sqlSession.getMapper(EmployeeMapper.class);
int employeeId = 1;
String name = null;
BigDecimal salary = null;
employeeMapper.getEmployeeInfo(employeeId, name, salary);
System.out.println("Name: " + name);
System.out.println("Salary: " + salary);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
这样我们就完成了在MyBatis中调用存储过程的整个操作,启动代码我们就可以看到ID为1的用户的姓名以及薪水信息。
总结
总结一下,在实际操作的过程中,我们当然不会这么使用,在真实的调用场景中可能会结合Controller、Service等处理逻辑来将这个存储过程更好的利用起来,当然了对于参数的配置、异常的处理在配置的时候一定要注意。很多人无法调用存储过程都是因为参数没有传对,所以在实际操作的时候一定要注意相关的操作。