一、存储过程
实际开发中,我们通常也会写一些存储过程,MyBatis也支持对存储过程的调用。
一个最简单的存储过程:
delimiter $$
create procedure test()
begin
select 'hello';
end $$
delimiter ;
存储过程的调用:
① select标签中statementType=“CALLABLE
② 标签体中调用语法:
{call procedure_name(#{param1_info},#{param2_info})}
二、存储过程-游标处理
1、在 Oracle 中创建一个带游标的存储过程,来查询分页数据
存储过程:
create or replace procedure
hello_test(
p_start in int, p_end in int, p_count out int, p_emps out sys_refcursor
) as
begin
select count(*) into p_count from employees;
open p_emps for
select * from (select rownum rn, e.* from employees where rownum <= p_end)
where rn >= p_start;
end hello_test;
2、在Java中声明分页查询的方法
分页查询类:
/**
*
* 封装分页查询数据
*/
public class OraclePage {
private int start;
private int end;
private int count;
private List<Employee> emps;
}
接口:
public void getPageByProcedure(OraclePage page);
3、MyBatis 调用存储过程
MyBatis对存储过程的游标提供了一个JdbcType=CURSOR的支持,可以智能的把游标读取到的数据,映射到我们声明的结果集中。
调用实例:
<!--
public void getPageByProcedure(OraclePage page);
1、使用 select 标签定义存储过程
2、statementType= "CALLABLE" 表示要调用存储过程
3、调用存储过程 {call procedure_name}
-->
<select id="getPageByProcedure" statementType="CALLABLE" databaseId="oracle">
{call hello_test(
#{start, mode=IN, jdbcType=INTEGER},
#{end, mode=IN, jdbcType=INTEGER},
#{count, mode=OUT, jdbcType=INTEGER},
#{emps, mode=OUT, jdbcType=CURSOR, javaType=ResultSet, resultMap=PageEmp},
)}
</select>
<resultMap id="PageEmp" type="com.njf.mybatis.bean.Employee">
<id column="EMPLOYEE_ID" property="id" />
<result column="LAST_NAME" property="lastName"/>
<result column="EMAIL" property="email"/>
</resultMap>
4、配置 Oracle 的运行环境
数据库配置文件:
orcl.driver=oracle.jdbc.OracleDriver
orcl.url=jdbc:oracle:thin:@localhost:1521:orcl
orcl.username=scott
orcl.password=123456
mybatis 的核心配置文件:
<environment id="oracle_dev">
<transactionManager type="JDBC" />
<dataSource type="POOLED">
<property name="driver" value="${orcl.driver}" />
<property name="url" value="${orcl.url}" />
<property name="username" value="${orcl.username}" />
<property name="password" value="${orcl.password}" />
</dataSource>
</environment>
<databaseIdProvider type="DB_VENDOR">
<property name="MySQL" value="mysql"/>
<property name="Oracle" value="oracle"/>
</databaseIdProvider>
5、测试
/**
* Oracle 分页
* 借助 rownum 行号,子查询
* 存储过程包装分页逻辑
*/
@Test
public void testProcedure() throws IOException {
//1、获取 sqlSessionFactory
SqlSessionFactory sqlSessionFactory = getsqlSessionFactory();
//2、获取 sqlSession 实例,获取批量执行器
SqlSession sqlSession = sqlSessionFactory.openSession();
try {
//3、获取接口的实现类对象
EmployeeMapper employeeMapper = sqlSession.getMapper(EmployeeMapper.class);
OraclePage oraclePage = new OraclePage();
oraclePage.setStart(1);
oraclePage.setEnd(5);
employeeMapper.getPageByProcedure(oraclePage);
System.out.println("总记录数:" + oraclePage.getCount());
System.out.println("查出的数据:" + oraclePage.getEmps().size());
System.out.println("查出的数据:");
oraclePage.getEmps().forEach(System.out::println);
} finally {
sqlSession.close();
}
}