MyBatis扩展应用
MyBatis-PageHelper(分页插件)
在使用MySQL的情况下,我们要创建分页需要使用limit语句,逻辑非常的复杂、麻烦,而MyBatis-PageHelper就为我们包装了这些语句,我们只需要写一个查询语句即可
导入相关依赖
构建maven工程,直接引入以下依赖
<!-- mybatis的分页插件 -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.1.10</version>
</dependency>
配置拦截器插件
在普通的MyBatis下,可以直接在全局配置文件中配置拦截器插件
<!--配置mybatis插件-->
<plugins>
<plugin interceptor="com.github.pagehelper.PageInterceptor"/>
</plugins>
在整合SSM框架下,使用Spring的属性配置方式
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 注意其他配置 -->
<property name="plugins">
<array>
<bean class="com.github.pagehelper.PageInterceptor">
<property name="properties">
<!--使用下面的方式配置参数,一行配置一个 -->
<value>
params=value1
</value>
</property>
</bean>
</array>
</property>
</bean>
如何在代码中使用
在查询方法之前调用PageHelper.startPage(),通过观察官方文档,发现只有跟在这个方法后面的第一个查询语句会被分页
可以使用PageInfo包装查询到的数据,这个比page的功能更加的强大,具体的用法在文档中查看即可
https://github.com/pagehelper/Mybatis-PageHelper/blob/master/wikis/zh/HowToUse.md
@Test
public void test02() throws IOException {
SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
SqlSession sqlSession = sqlSessionFactory.openSession();
try {
EmployeeMapper mapper = sqlSession.getMapper(EmployeeMapper.class);
//第一个参数表示当前页码,第二个参数为每页记录数
Page<Object> page = PageHelper.startPage(5, 2);
List<Employee> emps = mapper.getEmps();
//第二个参数为:连续显示多少页
PageInfo<Employee> info = new PageInfo<>(emps,5);
for(Employee emp : emps){
System.out.println(emp);
}
System.out.println("当前页码:" + page.getPageNum());
System.out.println("每页的记录数:" + page.getPageSize());
System.out.println("总页码:" + page.getPages());
System.out.println("总记录数:" + page.getTotal());
System.out.println("是否第一页:" + info.isIsFirstPage());
int[] nums = info.getNavigatepageNums();
System.out.println("显示页码");
for (int i = 0;i<nums.length;i++){
System.out.println(nums[i]);
}
}finally {
sqlSession.close();
}
}
批量操作
之前在整合SSM框架时,批量操作是通过循环拼接sql语句执行的,这里介绍 另外一种性能更强的方法
在默认创建executor时,创建的都是SimpleExecutor,而有一个BatchExecutor是可执行批量操作的
<!--void insertEmp(Employee emp);-->
<insert id="insertEmp">
insert into employee (last_name,gender,email) values (#{lastName},#{gender},#{email})
</insert>
@Test
public void test03() throws IOException {
SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
//设置创建executor的方式为batch,这是可执行批量语句的executor,默认是simple
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
long start = System.currentTimeMillis();
try {
EmployeeMapper mapper = sqlSession.getMapper(EmployeeMapper.class);
for(int i = 0;i < 10000;i++){
mapper.insertEmp(new Employee(UUID.randomUUID().toString().substring(0 ,5),i + "@123.com","0"));
}
sqlSession.commit();
long end = System.currentTimeMillis();
System.out.println("执行时长:" + (end-start));//执行时长:1592
}finally {
sqlSession.close();
}
}
MyBatis中的枚举类型处理
MyBatis类型处理都是通过实现TypeHandler接口实现的,而枚举类型的处理有两个处理器可以使用,枚举类型分为索引和名称,EnumOrdinalTypeHandler是通过索引存储的,EnumTypeHandle(默认)是通过名称存储的
我们在员工表的基础上创建一个empStatus枚举属性
public enum EmpStatus {
LOGIN,LOGOUT,REMOVE;
}
默认是使用EnumTypeHandle存储到数据库的,存储的数据库的值为LOGOUT
@Test
public void test04() throws IOException {
SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
//设置创建executor的方式为batch,这是可执行批量语句的executor,默认是simple
SqlSession sqlSession = sqlSessionFactory.openSession();
long start = System.currentTimeMillis();
try {
EmployeeMapper mapper = sqlSession.getMapper(EmployeeMapper.class);
mapper.insertEmp(new Employee("enum","enum@123.com","1", EmpStatus.LOGOUT));
sqlSession.commit();
}finally {
sqlSession.close();
}
}
可以通过修改全局配置文件,修改默认的枚举类型处理器,修改为EnumOrdinalTypeHandler,存储值为1
<typeHandlers>
<typeHandler handler="org.apache.ibatis.type.EnumOrdinalTypeHandler" javaType="com.yellowstar.bean.EmpStatus"></typeHandler>
</typeHandlers>
实际开发过程中,我们经常不满足于使用默认的枚举类型处理器,比如将枚举类修改为以下形式,我们想在数据库中插入自定义的code或者msg数据,那么需要自定义类型处理器
public enum EmpStatus {
LOGIN(100,"已登录"),LOGOUT(200,"已登出"),REMOVE(300,"不存在");
Integer code;
String msg;
EmpStatus(Integer code, String msg) {
this.code = code;
this.msg = msg;
}
public Integer getCode() {return code;}
public void setCode(Integer code) {this.code = code;}
public String getMsg() {return msg;}
public void setMsg(String msg) {this.msg = msg;}
//根据code返回枚举类对象
public static EmpStatus getEmpStatusByCode(Integer code){
switch (code){
case 100:
return LOGIN;
case 200:
return LOGOUT;
case 300:
return REMOVE;
default:
return LOGOUT;
}
}
}
创建自定义处理器有两种方法:实现TypeHandler接口或继承BaseTypeHandler类,我们使用实现接口并重写方法的方式
public class EmpStatusTypeHandler implements TypeHandler<EmpStatus> {
// 定义当前数据如何保存到数据库中
@Override
public void setParameter(PreparedStatement preparedStatement, int i, EmpStatus empStatus, JdbcType jdbcType) throws SQLException {
System.out.println("要保存的状态码:" + empStatus.getCode());
preparedStatement.setInt(i,empStatus.getCode());
}
// 获取数据库的数据
@Override
public EmpStatus getResult(ResultSet resultSet, String s) throws SQLException {
//需要根据从数据库中拿到的枚举的状态码返回一个枚举对象
int code = resultSet.getInt(s);
System.out.println("从数据库中获取的状态码:"+code);
EmpStatus empStatus = EmpStatus.getEmpStatusByCode(code);
return empStatus;
}
@Override
public EmpStatus getResult(ResultSet resultSet, int i) throws SQLException {
int code = resultSet.getInt(i);
System.out.println("从数据库中获取的状态码:"+code);
EmpStatus empStatus = EmpStatus.getEmpStatusByCode(code);
return empStatus;
}
@Override
public EmpStatus getResult(CallableStatement callableStatement, int i) throws SQLException {
int code = callableStatement.getInt(i);
System.out.println("从数据库中获取的状态码:"+code);
EmpStatus empStatus = EmpStatus.getEmpStatusByCode(code);
return empStatus;
}
}