Mybatis之应用场景
一 PageHelper插件进行分页
- PageHelper是MyBatis中非常方便的第三方分页 插件
- 官方文档
https://github.com/pagehelper/MybatisPageHelper/blob/master/README_zh.md
我们可以参考文档快速使用分页插件进行开发 - 使用步骤
(1)导入相关包pagehelper-x.x.x.jar 和 jsqlparser0.9.5.jar。
<!-- https://mvnrepository.com/artifact/com.github.pagehelper/pagehelper -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>4.1.6</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.github.jsqlparser/jsqlparser -->
<dependency>
<groupId>com.github.jsqlparser</groupId>
<artifactId>jsqlparser</artifactId>
<version>0.9.4</version>
</dependency>
(2)在MyBatis全局配置文件中配置分页插件
mybatis-config.xml
<plugins>
<!-- 配置pagehelper分页插件 -->
<!-- PageHelper4.1.1 -->
<plugin interceptor="com.github.pagehelper.PageHelper">
<property name="dialect" value="mysql" />
<property name="offsetAsPageNum" value="false" />
<property name="rowBoundsWithCount" value="false" />
<property name="pageSizeZero" value="true" />
<property name="reasonable" value="false" />
<property name="supportMethodsArguments" value="false" />
<property name="returnPageInfo" value="none" />
</plugin>
</plugins>
(3)使用PageHelper提供的方法进行分页,使用PageInfo封装返回结果
4. 案例
(0) 依赖和配置文件参考上面内容
(1)contorller层代码
@Controller
public class EmpController {
//依赖注入
@Autowired
private EmpService empService;
/**
* 分页插件使用
* @param pageNum 当前页
* @param model 作用域
* @return
*/
@RequestMapping("/fenye")
public String fenye(Integer pageNum,Model model){
//判断前端查过来的是否为null
if(pageNum==null){
pageNum=1;
}
//每页条数
Integer pageSize=5;
//从后台查询数据并返回分页对象传到ServiceImpl
//pageNum 当前页、pageSize 每页条数
PageInfo<Emp> p=empService.fenye(pageNum,pageSize);
//将查出来的信息存储到Model作用域
model.addAttribute("p", p);
return "list";
}
}
(2)Service层代码
@Service
public class EmpServiceImpl implements EmpService {
//依赖注入
@Autowired
private EmpMapper empMapper;
/**
* @param pageNum 当前页
* @param pageSize 每页条数
* @return
*/
@Override
public PageInfo<Emp> fenye(Integer pageNum, Integer pageSize) {
//开启分页
PageHelper.startPage(pageNum,pageSize);
//获取查询数据放入分页对象、
// 查询时无需关注查询的条数 不需要向Dao层中的方法传入limit后边的两个参数 (limit 1 ,5)
//调用Dao层方法
List<Emp> list=empMapper.findAll();
///封装pageInfo对象并返回 PageInfo可以看到源码你就明白所有意思
PageInfo<Emp> p=new PageInfo<Emp>(list);
return p;
}
}
(3)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="cn.bgs.dao.EmpMapper">
<resultMap type="cn.bgs.pojo.Emp" id="emp_dept">
<id column="id" property="id"/>
<result column="ename" property="eName"/>
<result column="sal" property="sal"/>
<result column="did" property="did"/>
<association property="dept" javaType="cn.bgs.pojo.Dept">
<id property="did" column="did"/>
<result property="dname" column="dname"/>
</association>
</resultMap>
<!-- 分页插件查询 List<Emp> findAll(); 两表连查-->
<select id="findAll" resultMap="emp_dept">
select * from emp e,dept d where e.did=d.did
</select>
</mapper>
(4)页面代码
(1)css代码:
ul.pagination {
display: inline-block;
padding: 0;
margin: 0;
}
ul.pagination li {display: inline;}
ul.pagination li a {
color: black;
float: left;
padding: 8px 16px;
text-decoration: none;
border-radius: 5px;
}
ul.pagination li a.active {
background-color: #4CAF50;
color: white;
border-radius: 5px;
}
ul.pagination li a:hover:not(.active) {background-color: #ddd;}
(2)页面代码:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<!--引入分页查询按钮的CSS格式-->
<link href="${pageContext.request.contextPath}/css/page.css" rel="stylesheet" type="text/css"/>
<title>分页查询</title>
</head>
<body>
<center>
<h1>分页显示</h1>
<!-- 设置表格格式-->
<table border="1" cellpadding="0" cellspacing="0" width="50%" align="center">
<tr align="center">
<th>编号</th>
<th>姓名</th>
<th>工资</th>
<th>部门</th>
</tr>
<!--
list是PageInfo<T>的结果集
这必须是list切记不要写成自己的pojo类属性
-->
<c:forEach items="${p.list }" var="emp">
<tr align="center">
<td>${emp.id }</td>
<td>${emp.eName }</td>
<td>${emp.sal }</td>
<td>${emp.dept.dname }</td>
</tr>
</c:forEach>
</table>
<!-- 分页查询按钮 不要改(pageNum、pages等)这些都是插件类提供好的属性变量
拿去用就改一下(/fenye)这个映射的路径
-->
<form action="${pageContext.request.contextPath}/fenye" method="post">
<ul class="pagination">
<li><a href="${pageContext.request.contextPath}/fenye?pageNum=1">首页</a></li>
<c:if test="${p.pageNum>1}">
<li><a href="${pageContext.request.contextPath}/fenye?pageNum=${p.pageNum-1}">上一页</a></li>
</c:if>
<c:forEach begin="1" end="${p.pages}" step="1" var="pageNum">
<li><a href="${pageContext.request.contextPath}/fenye?pageNum=${pageNum}">${pageNum}</a></li>
</c:forEach>
<c:if test="${p.pageNum<p.pages}">
<li><a href="${pageContext.request.contextPath}/fenye?pageNum=${p.pageNum+1}">下一页</a></li>
</c:if>
<li><a href="${pageContext.request.contextPath}/fenye?pageNum=${p.pages}">末页</a></li>
<li><a>共${p.pages }页</a></li>
<li><a>跳到<input type="text" name="pageNum" style="width: 20px; height: 20px">页</a></li>
<li><a><input type="submit" value="GO"/></a></li>
</ul>
</form>
</center>
</body>
</html>
(5)效果图
二 批量操作
- 概述
(1)默认的 openSession() 方法没有参数,它会创建有如下特性:
– 会开启一个事务(不自动提交)
– 连接对象会从由活动环境配置的数据源实例得到
– 事务隔离级别将会使用驱动或数据源的默认设置
– 预处理语句不会被复用,也不会批量处理更新
(2)openSession 方法的 ExecutorType类型的参数,枚举类型:
– ExecutorType.SIMPLE: 这个执行器类型不做特殊的事情(这是默认装配的)。它为每个语句的执行创建一个新的预处理语句。
– ExecutorType.REUSE: 这个执行器类型会复用预处理语句
– ExecutorType.BATCH: 这个执行器会批量执行所有更新语句 - 批量操作
(1)批量操作我们是使用MyBatis提供的BatchExecutor进行的, 他的底层就是通过jdbc攒sql的方式进行的。我们可以让他 攒够一定数量后发给数据库一次。
案例
public void test01() {
SqlSession openSession = build.openSession(ExecutorType. BATCH );
UserDao mapper = openSession.getMapper(UserDao.class);
longstart = System. currentTimeMillis();
for (int i = 0; i < 1000000; i++) {
String name = UUID. randomUUID().toString().substring(0, 5);
mapper.addUser(newUser(null, name, 13)); } openSession.commit();
openSession.close();
longend = System. currentTimeMillis();
System. out .println( " 耗时时间: " +(end - start));
}
- 与Spring整合中,我们推荐额外的配置一个可以专门用来执行批量操作的sqlSession,需要用到批量操作的时候,我们可以注入配置的这个批量 SqlSession。通过他获取到mapper映射器进行操作。
注意:
(1)批量操作是在**session.commit()以后才发送sql语句给数据库进行执行的
(2)如果我们想让其提前执行,以方便后续可能的查询操作获取数据,我们可以使用sqlSession.flushStatements()**方 法,让其直接冲刷到数据库进行执行。
三 存储过程
- 概述
(1)实际开发中,我们通常也会写一些存储过程, MyBatis也支持对存储过程的调
(2)一个最简单的存储过程
delimiter $$
create procedure test()
begin
select 'hello';
end
$$ delimiter ;
(3)存储过程的调用
1 select标签中
statementType=“CALLABLE“
2 标签体中调用语法:
{call procedure_name(//存储过程名
#{param1_info},//参数
#{param2_info}
)}
- 存储过程游标处理
MyBatis对存储过程的游标提供了一个JdbcType=CURSOR的支持, 可以智能的把游标读取到的数据,映射到我们声明的结果集中
案例:
(1)实体类
(2)数据库连接池配置
orcl.driver=oracle.jdbc.OracleDriver
orcl.url=jdbc:oracle:thin:@localhost:1521:orcl
orcl.username=scott
orcl.password=123456
(3)配置文件
<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>
(4)存储过程
(5)Mapper映射文件
四 typeHandler处理枚举
- 自定义TypeHandler步骤
(1)定义TypeHandler实现TypeHandler接口或者继承BaseTypeHandler
(2)使用**@MappedTypes定义处理的java类型 ,使用@MappedJdbcTypes定义jdbcType类型
(3)在自定义结果集标签或者参数处理的时候声明使用自定义 TypeHandler进行处理** 或者在全局配置TypeHandler要处理的javaType - 案例
(1)枚举类
(2)自定义TypeHanler类
(3)测试全局配置EnumOrdinalTypeHandler
(4)测试全局配置EnumTypeHandler
(5)测试自定义TypeHanler