一、存储过程调用关键
1、SQL映射文件中,使用select标签定义调用存储过程
(1)statementType=”CALLABLE”:表示要调用存储过程
(2){call procedure_name(params)}
2、编辑存储过程对象,用于保存存储过程的输入参数和输出参数
二、存储过程调用-mysql
1、搭建数据库
id last_name gender email
1 mike 0 [email protected]
2 book 0 [email protected]
3 tom 1 [email protected]
4 jerry 1 [email protected]
5 hhee 1 [email protected]
6 jerry4 1 [email protected]
7 smith0x1 1 [email protected]
8 mas 1 [email protected]
9 smith0x1 1 [email protected]
10 allen0x1 0 [email protected]
2、创建存储过程
USE `mybatis`;
DROP PROCEDURE IF EXISTS proc_employee;
DELIMITER //
CREATE PROCEDURE proc_employee(IN p_start INT, IN p_end INT,OUT p_count INT)
BEGIN
SELECT COUNT(*) INTO p_count FROM `tbl_employee`;
SELECT * FROM ( SELECT a.* FROM `tbl_employee` a WHERE a.`id` < p_end) b
WHERE b.`id` >p_start;
END//
DELIMITER ;
特别注意点:
开头部分:DELIMITER //【这两斜杠前面有空格,需要注意】
结尾部分:DELIMITER ;【分号前面也有个空格,需要注意】
在定义过程时,使用DELIMITER // 命令将语句的结束符号从分号 ;
临时改为//,使得过程体中使用的分号被直接传递到服务器,而不会被客户端(如mysql)解释。
3、mysql客户端测试端调用存储过程
set @p_count=1;
CALL proc_employee(1,8,@p_count);
select @p_count;
4、编辑全局配置文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC" />
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/mybatis" />
<property name="username" value="root" />
<property name="password" value="Cool123!" />
</dataSource>
</environment>
</environments>
<!-- 5、databaseIdProvider:支持多数据库厂商的;
type="DB_VENDOR":VendorDatabaseIdProvider
作用就是得到数据库厂商的标识(驱动getDatabaseProductName()),mybatis就能根据数据库厂商标识来执行不同的sql;
MySQL,Oracle,SQL Server,xxxx
-->
<databaseIdProvider type="DB_VENDOR">
<!-- 为不同的数据库厂商起别名 -->
<property name="MySQL" value="mysql"/>
<property name="Oracle" value="oracle"/>
<property name="SQL Server" value="sqlserver"/>
</databaseIdProvider>
<!-- 将我们写好的sql映射文件(EmployeeMapper.xml)一定要注册到全局配置文件(mybatis-config.xml)中
如果 数据库全局文件 和 子配置文件 不在同一个目录 ,就需要 /目录/目录/.../EmployeeMapper_old.xml
-->
<mappers>
<!-- 新方法操作mybatis 需要 的配置文件 -->
<mapper resource="EmployeeMapper.xml" />
</mappers>
</configuration>
5、编辑javabean
Employee.java
package com.mybatis.bean;
public class Employee {
private Integer id;
private String lastName;
private String email;
private String gender;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public Employee(){
super();
}
public Employee(String lastName, String email, String gender) {
super();
this.lastName = lastName;
this.email = email;
this.gender = gender;
}
@Override
public String toString() {
return "Employee [id=" + id + ", lastName=" + lastName + ", email=" + email + ", gender=" + gender + "]";
}
}
存储过程的bean文件 ProcPage.java
package com.mybatis.bean;
import java.util.List;
/**
* 封装分页查询数据
* @author lfy
*
*/
public class ProcPage {
private int start;
private int end;
private int count;
private List<Employee> emps;
public int getStart() {
return start;
}
public void setStart(int start) {
this.start = start;
}
public int getEnd() {
return end;
}
public void setEnd(int end) {
this.end = end;
}
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
public List<Employee> getEmps() {
return emps;
}
public void setEmps(List<Employee> emps) {
this.emps = emps;
}
}
6、配置mapper接口
EmployeeMapper.java
package com.mybatis.mapper;
import java.util.List;
import com.mybatis.bean.Employee;
import com.mybatis.bean.ProcPage;
public interface EmployeeMapper {
public List<Employee> getPageByProcedure(ProcPage page);
}
7、配置SQL映射文件
EmployeeMapper.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.mybatis.mapper.EmployeeMapper">
<!-- public void getPageByProcedure();
1、使用select标签定义调用存储过程
2、statementType="CALLABLE":表示要调用存储过程
3、{call procedure_name(params)}
-->
<select id="getPageByProcedure" statementType="CALLABLE" databaseId="mysql" resultMap="PageEmp">
{
call proc_employee(
#{start,mode=IN,jdbcType=INTEGER},
#{end,mode=IN,jdbcType=INTEGER},
#{count,mode=OUT,jdbcType=INTEGER}
)
}
</select>
<resultMap type="com.mybatis.bean.Employee" id="PageEmp">
<id column="ID" property="id"/>
<result column="LAST_NAME" property="lastName"/>
<result column="EMAIL" property="email"/>
</resultMap>
</mapper>
8、Junit单元测试
package com.mybatis.test;
import java.io.IOException;
import java.io.InputStream;
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 org.junit.Test;
import com.mybatis.bean.ProcPage;
import com.mybatis.mapper.EmployeeMapper;
/**
* 1、接口式编程
* 原生: Dao ====> DaoImpl
* mybatis: Mapper ====> xxMapper.xml
*
* 2、SqlSession代表和数据库的一次会话;用完必须关闭;
* 3、SqlSession和connection一样她都是非线程安全。每次使用都应该去获取新的对象。(就是不要放在共享成员变量里面,A线程用完释放,B线程再用就为空了)
* 4、mapper接口没有实现类,但是mybatis会为这个接口生成一个代理对象。
* (将接口和xml进行绑定)
* EmployeeMapper empMapper = sqlSession.getMapper(EmployeeMapper.class);
* 5、两个重要的配置文件:
* mybatis的全局配置文件:包含数据库连接池信息,事务管理器信息等...系统运行环境信息
* sql映射文件:保存了每一个sql语句的映射信息:
* 将sql抽取出来。
*
*/
public class MybatisTest {
public SqlSessionFactory getSqlSessionFactory() throws IOException {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
return new SqlSessionFactoryBuilder().build(inputStream);
}
/**
* mysql分页:
* 存储过程包装分页逻辑
* @throws IOException
*/
@Test
public void testProcedure() throws IOException{
SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
SqlSession openSession = sqlSessionFactory.openSession();
try{
EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class);
ProcPage page = new ProcPage();
page.setStart(5);
page.setEnd(8);
page.setEmps(mapper.getPageByProcedure(page));
System.out.println("总记录数:"+page.getCount());
System.out.println("查出的数据:"+page.getEmps().size());
System.out.println("查出的数据:"+page.getEmps());
}finally{
openSession.close();
}
}
}
三、存储过程调用流程-oracle
基本和mysql相同,部分不相同。【因为存储过程不一样,存储过程对应有四个参数,导致后面的操作稍微不同】
1、数据库存储过程:
create or replace procedure
proc_employee(p_start in int,
p_end in int,
p_count out int,
ref_cur out sys_refcursor) AS
BEGIN
select count(*) into p_count from tbl_employee;
open ref_cur for
select * from (select e.*,rownum as rn) from tbl_employee e where rownum <p_end)
where rn >p_start;
END proc_employee;
2、mapper接口文件
package com.mybatis.mapper;
import java.util.List;
import com.mybatis.bean.Employee;
import com.mybatis.bean.ProcPage;
public interface EmployeeMapper {
public void getPageByProcedure(ProcPage page);
}
3、SQL映射文件
<mapper namespace="com.mybatis.mapper.EmployeeMapper">
<!-- public void getPageByProcedure();
1、使用select标签定义调用存储过程
2、statementType="CALLABLE":表示要调用存储过程
3、{call procedure_name(params)}
-->
<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 type="com.mybatis.bean.Employee" id="PageEmp">
<id column="EMPLOYEE_ID" property="id"/>
<result column="LAST_NAME" property="email"/>
<result column="EMAIL" property="email"/>
</resultMap>
</mapper>
4、Junit单元测试
/**
* oracle分页:
* 借助rownum:行号;子查询;
* 存储过程包装分页逻辑
* @throws IOException
*/
@Test
public void testProcedure() throws IOException{
SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
SqlSession openSession = sqlSessionFactory.openSession();
try{
EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class);
OraclePage page = new OraclePage();
page.setStart(1);
page.setEnd(5);
mapper.getPageByProcedure(page);
System.out.println("总记录数:"+page.getCount());
System.out.println("查出的数据:"+page.getEmps().size());
System.out.println("查出的数据:"+page.getEmps());
}finally{
openSession.close();
}
}