目录
一.二级缓存
二.一对一关联查询
三.一对多关联查询
四.注解开发与映射文件开发的对比
五.PageHelper分页插件
一.二级缓存
MyBatis
默认开启一级缓存,接下来我们学习如何在注解开发时使用二级缓存:
1
(1)POJO
类实现
Serializable
接口。
(2)在
MyBatis
配置文件添加如下设置:
下面的这个配置其实可以不加,因为这个配置默认就是true
在核心配置文件的的中添加如下配置
(3)
在持久层接口上方加注解
@CacheNamespace(blocking=true)
,该接口的
所有方法
都支持二级缓存。
(4)
测试二级缓存
TestUserMapper2.java:
import com.first.mapper.UserMapper;
import com.first.pojo.User;
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.After;
import org.junit.Before;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
public class TestUserMapper2 {
//前置方法:测试类里的测试方法执行之前都会先执行前置方法
@Test
public void testCache() throws IOException {
//(1)读取核心配置文件
InputStream is= Resources.getResourceAsStream("SqlMapConfig.xml");
//(2)创建SqlSessionFactoryBuilder对象
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
//(3)SqlSessionFactoryBuilder对象获取SqlSessionFactory对象
SqlSessionFactory factory = builder.build(is);
//(4)SqlSessionFactory对象获取不同SqlSession对象
SqlSession session1 = factory.openSession();
SqlSession session2 = factory.openSession();
//(5)SqlSession对象获取代理对象,即对应类的对象
User user1 = session1.getMapper(UserMapper.class).findById(1);
System.out.println(user1);
System.out.println(user1.hashCode());
//清空一级缓存,将数据保存到二级缓存
session1.commit();
User user2 = session2.getMapper(UserMapper.class).findById(1);
System.out.println(user2);
System.out.println(user2.hashCode());
}
}
输出:
[06/01 14:40:38] 1450 [ main] DEBUG rst.mapper.UserMapper.findById - ==> Preparing: select * from user where id=?
[06/01 14:40:38] 1540 [ main] DEBUG rst.mapper.UserMapper.findById - ==> Parameters: 1(Integer)
[06/01 14:40:38] 1741 [ main] DEBUG rst.mapper.UserMapper.findById - <== Total: 1
User{id=1, username='小热', sex='男', address='北京'}
1327536153
[06/01 14:40:38] 1843 [ main] WARN .ibatis.io.SerialFilterChecker - As you are using functionality that deserializes object streams, it is recommended to define the JEP-290 serial filter. Please refer to https://docs.oracle.com/pls/topic/lookup?ctx=javase15&id=GUID-8296D8E8-2B93-4B9A-856E-0A65AF9B8C66
[06/01 14:40:38] 1862 [ main] DEBUG com.first.mapper.UserMapper - Cache Hit Ratio [com.first.mapper.UserMapper]: 0.5
User{id=1, username='小热', sex='男', address='北京'}
可以看见两次输出的对象内容是一样的,但是第一次是查询了数据库,第一次查询之后返回结果并将结果放到一级缓存中,然后又执行了session1.commit();用来清空一级缓存,将数据保存到二级缓存 ,而在二级缓存中,存储的是数据,而不是对象,所以第二次查询时,从二级缓存中取出数据拼接成对象,所以第一次和第二次的对象hashCode不一样!如果关掉二级缓存的话,就只能两次都查询数据库了。
二.一对一关联查询
在
MyBatis
的注解开发中对于多表查询只支持分解查询(N+1),不支持连接查询。
示例:查询所有学生,把学生对应的班级也查询出来(一个学生对应一个班级)
(1)创建实体类
上篇文章已经创建过,Classes和Student类
(2)创建分解后的查询方法
在mapper下创建接口文件StudentMapper.java和ClassesMapper.java
ClassesMapper.java:
package com.first.mapper;
import com.first.pojo.Classes;
import org.apache.ibatis.annotations.Select;
public interface ClassesMapper {
//根据cid查询班级
@Select("select * from classes where cid= #{cid}")
Classes findByCid(int cid);
}
StudentMapper.java:
后面还得修改
package com.first.mapper;
import com.first.pojo.Student;
import org.apache.ibatis.annotations.Select;
import java.util.List;
public interface StudentMapper {
//查询所有学生信息
@Select("select * from student")
List findAll();
}
因为这个查询中student是主表,根据student表中的classId与classes表中的cid将两张表联系起来,所以classes表是从表,查询结果中除了有Student类中定义的普通属性外,还要有一个Classes的类对象!所以这就需要自定义映射关系!
(3)主表的查询配置自定义映射关系
StudentMapper.java:
package com.first.mapper;
import com.first.pojo.Student;
import org.apache.ibatis.annotations.One;
import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.Results;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.mapping.FetchType;
import java.util.List;
public interface StudentMapper {
//查询所有学生信息,所以classId也能够被查出来,虽然Student类中没有定义classId属性
@Select("select * from student")
//自定义映射关系
@Results(id = "studentMapper" ,value = {
@Result(id = true,property = "sid",column = "sid"),
@Result(property = "name",column = "name"),
@Result(property = "age",column = "age"),
@Result(property = "sex",column = "sex"),
@Result(property = "classes",column = "classId",
one = @One(select = "com.first.mapper.ClassesMapper.findByCid",
fetchType = FetchType.EAGER))
})
List findAll();
}
(4)测试
新建测试类TestManyTables
import com.first.mapper.StudentMapper;
import com.first.mapper.UserMapper;
import com.first.pojo.Student;
import com.first.pojo.User;
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.After;
import org.junit.Before;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
public class TestManyTables {
//全局变量
InputStream is=null;
SqlSession session =null;
StudentMapper userMapper =null;
//前置方法:测试类里的测试方法执行之前都会先执行前置方法
@Before
public void before() throws IOException {
//(1)读取核心配置文件
is= Resources.getResourceAsStream("SqlMapConfig.xml");
//(2)创建SqlSessionFactoryBuilder对象
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
//(3)SqlSessionFactoryBuilder对象获取SqlSessionFactory对象
SqlSessionFactory factory = builder.build(is);
//(4)SqlSessionFactory对象获取SqlSession对象
session = factory.openSession();
}
后置方法:测试类里的测试方法执行之后都会执行后置方法
@After
public void after() throws IOException {
//(7)释放资源
session.close();
is.close();
}
@Test
public void findAllStudent(){
//(5)SqlSession对象获取代理对象,即对应类的对象
StudentMapper studentMapper = session.getMapper(StudentMapper.class);
List all = studentMapper.findAll();
all.forEach(System.out::println);
}
}
输出:
Student{sid=1, name='张三', age=10, sex='男', classes=Classes{cid=1, className='三年一班', studentList=null}}
Student{sid=2, name='李四', age=10, sex='女', classes=Classes{cid=1, className='三年一班', studentList=null}}
Student{sid=3, name='尚尚', age=10, sex='男', classes=Classes{cid=2, className='三年二班', studentList=null}}
Student{sid=4, name='百战', age=11, sex='男', classes=Classes{cid=2, className='三年二班', studentList=null}}
Student{sid=5, name='王五', age=10, sex='男', classes=Classes{cid=2, className='三年二班', studentList=null}}
三.一对多关联查询
本例是查询所有班级,每个班级又对应多个学生,所以是一对多,班级表是主表,而学生表是从表。
(1)创建分解后的查询方法
在ClassesMapper.java中增加接口函数
后面还有修改,即(3)
//查询所有班级
@Select("select * from classes")
List findAll();
在StudentMapper.java中增加接口函数
//根据班级ID查询学生
@Select("select * from student where classId = #{cid}")
List findByClassId(int classId);
(2)主表的查询配置自定义映射关系
//查询所有班级
@Select("select * from classes")
@Results(id = "classMapper",value = {
@Result(id = true,property = "cid",column = "cid"),
@Result(property = "className",column = "className"),
//many:表示该属性是一个集合
@Result(property = "studentList",column = "cid",
many = @Many(select = "com.first.mapper.StudentMapper.findByClassId",
//一对多一般用延迟加载
fetchType = FetchType.LAZY))
})
List findAll();
(3)测试
//一对多
@Test
public void findAllClasses(){
ClassesMapper classesMapper = session.getMapper(ClassesMapper.class);
List all = classesMapper.findAll();
all.forEach(System.out::println);
}
输出:
[06/01 16:49:13] 867 [ main] DEBUG t.mapper.ClassesMapper.findAll - ==> Preparing: select * from classes
[06/01 16:49:13] 954 [ main] DEBUG t.mapper.ClassesMapper.findAll - ==> Parameters:
[06/01 16:49:14] 1292 [ main] DEBUG t.mapper.ClassesMapper.findAll - <== Total: 2
[06/01 16:49:14] 1295 [ main] DEBUG er.StudentMapper.findByClassId - ==> Preparing: select * from student where classId = ?
[06/01 16:49:14] 1295 [ main] DEBUG er.StudentMapper.findByClassId - ==> Parameters: 1(Integer)
[06/01 16:49:14] 1352 [ main] DEBUG er.StudentMapper.findByClassId - <== Total: 2
Classes{cid=1, className='三年一班', studentList=[Student{sid=1, name='张三', age=10, sex='男', classes=null}, Student{sid=2, name='李四', age=10, sex='女', classes=null}]}
[06/01 16:49:14] 1353 [ main] DEBUG er.StudentMapper.findByClassId - ==> Preparing: select * from student where classId = ?
[06/01 16:49:14] 1354 [ main] DEBUG er.StudentMapper.findByClassId - ==> Parameters: 2(Integer)
[06/01 16:49:14] 1359 [ main] DEBUG er.StudentMapper.findByClassId - <== Total: 3
Classes{cid=2, className='三年二班', studentList=[Student{sid=3, name='尚尚', age=10, sex='男', classes=null}, Student{sid=4, name='百战', age=11, sex='男', classes=null}, Student{sid=5, name='王五', age=10, sex='男', classes=null}]}
四.注解开发与映射文件开发的对比
注解开发更快,映射文件维护方便!
MyBatis
中更推荐使用映射文件开发,
Spring
、
SpringBoot
更推荐注解方式。具体使用要视项目情况而定。它们的优点对比如下:
映射文件:
- 代码与Sql语句是解耦的,修改时只需修改配置文件,无需修改源码。 因为注解当时修改sql语句后,java源码需要重新编译,但是映射文件方式直接修改即可!
- Sql语句集中,利于快速了解和维护项目。
- 级联查询支持连接查询和分解查询两种方式,注解开发只支持分解查询。
注解:
- 配置简单,开发效率高。
- 类型安全,在编译期即可进行校验,不用等到运行时才发现错误。
五.PageHelper分页插件
如果你也在用MyBatis,建议尝试该分页插件,这一定是最方便使用的分页插件。分页插件支持任何复杂的单表、多表分页。
开发过程中如果要进行分页查询,需要传入页数和每页条数。返回页面数据,总条数,总页数,当前页面,每页条数等数据。此时使用PageHelper插件可以快速帮助我们获取这些数据。
PageHelper是一款非常好用的开源免费的Mybatis第三方分页插件。使用该插件时,只要传入分页参数,即可自动生成页面对象。 我们使用该插件分页查询所有用户:
(1)引入依赖
在pom.xml文件中配置,配置完成后,刷新maven
com.github.pagehelper
pagehelper
5.3.0
(2)Mybatis配置文件中配置PageHelper插件
在SqlMapConfig.xml的中添加如下代码
(3)使用PageHelper插件
在TestUserMapper.java中测试
//测试分页插件
@Test
public void testFindPage(){
//1.设置分页参数 参数一:起始页(此插件从1开始,而不是0);参数二:每页条数
PageHelper.startPage(1,3);
//2.正常查询
List all = userMapper.findAll();
//3.封装查询结果,生成页面对象
PageInfo pageInfo = new PageInfo(all);
//4.打印页面对象的属性
//是每页的结果集,而不是所有数据
System.out.println("结果集:"+pageInfo.getList());
System.out.println("总条数:"+pageInfo.getTotal());
System.out.println("总页数:"+pageInfo.getPages());
System.out.println("当前页:"+pageInfo.getPageNum());
System.out.println("每页条数:"+pageInfo.getSize());
}
输出:
[06/01 21:20:18] 2491 [ main] DEBUG apper.UserMapper.findAll_COUNT - ==> Preparing: SELECt count(0) FROM user
[06/01 21:20:18] 2576 [ main] DEBUG apper.UserMapper.findAll_COUNT - ==> Parameters:
[06/01 21:20:19] 2827 [ main] DEBUG apper.UserMapper.findAll_COUNT - <== Total: 1
[06/01 21:20:19] 2828 [ main] DEBUG com.first.mapper.UserMapper - Cache Hit Ratio [com.first.mapper.UserMapper]: 0.0
[06/01 21:20:19] 2828 [ main] DEBUG irst.mapper.UserMapper.findAll - ==> Preparing: select * from user LIMIT ?
[06/01 21:20:19] 2828 [ main] DEBUG irst.mapper.UserMapper.findAll - ==> Parameters: 3(Integer)
[06/01 21:20:19] 2843 [ main] DEBUG irst.mapper.UserMapper.findAll - <== Total: 3
结果集:Page{count=true, pageNum=1, pageSize=3, startRow=0, endRow=3, total=9, pages=3, reasonable=false, pageSizeZero=false}[User{id=1, username='小热', sex='男', address='北京'}, User{id=2, username='小巴', sex='男', address='上海'}, User{id=3, username='小赵', sex='女', address='广州'}]
总条数:9
总页数:3
当前页:1
每页条数:3
可以自己调整起始页参数和每页条数来测试一下!
(3) 在持久层接口上方加注解 @CacheNamespace(blocking=true) ,该接口的 所有方法 都支持二级缓存。 (4) 测试二级缓存
TestUserMapper2.java:
import com.first.mapper.UserMapper;
import com.first.pojo.User;
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.After;
import org.junit.Before;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
public class TestUserMapper2 {
//前置方法:测试类里的测试方法执行之前都会先执行前置方法
@Test
public void testCache() throws IOException {
//(1)读取核心配置文件
InputStream is= Resources.getResourceAsStream("SqlMapConfig.xml");
//(2)创建SqlSessionFactoryBuilder对象
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
//(3)SqlSessionFactoryBuilder对象获取SqlSessionFactory对象
SqlSessionFactory factory = builder.build(is);
//(4)SqlSessionFactory对象获取不同SqlSession对象
SqlSession session1 = factory.openSession();
SqlSession session2 = factory.openSession();
//(5)SqlSession对象获取代理对象,即对应类的对象
User user1 = session1.getMapper(UserMapper.class).findById(1);
System.out.println(user1);
System.out.println(user1.hashCode());
//清空一级缓存,将数据保存到二级缓存
session1.commit();
User user2 = session2.getMapper(UserMapper.class).findById(1);
System.out.println(user2);
System.out.println(user2.hashCode());
}
}
输出:
[06/01 14:40:38] 1450 [ main] DEBUG rst.mapper.UserMapper.findById - ==> Preparing: select * from user where id=?
[06/01 14:40:38] 1540 [ main] DEBUG rst.mapper.UserMapper.findById - ==> Parameters: 1(Integer)
[06/01 14:40:38] 1741 [ main] DEBUG rst.mapper.UserMapper.findById - <== Total: 1
User{id=1, username='小热', sex='男', address='北京'}
1327536153
[06/01 14:40:38] 1843 [ main] WARN .ibatis.io.SerialFilterChecker - As you are using functionality that deserializes object streams, it is recommended to define the JEP-290 serial filter. Please refer to https://docs.oracle.com/pls/topic/lookup?ctx=javase15&id=GUID-8296D8E8-2B93-4B9A-856E-0A65AF9B8C66
[06/01 14:40:38] 1862 [ main] DEBUG com.first.mapper.UserMapper - Cache Hit Ratio [com.first.mapper.UserMapper]: 0.5
User{id=1, username='小热', sex='男', address='北京'}
可以看见两次输出的对象内容是一样的,但是第一次是查询了数据库,第一次查询之后返回结果并将结果放到一级缓存中,然后又执行了session1.commit();用来清空一级缓存,将数据保存到二级缓存 ,而在二级缓存中,存储的是数据,而不是对象,所以第二次查询时,从二级缓存中取出数据拼接成对象,所以第一次和第二次的对象hashCode不一样!如果关掉二级缓存的话,就只能两次都查询数据库了。
二.一对一关联查询 在 MyBatis 的注解开发中对于多表查询只支持分解查询(N+1),不支持连接查询。 示例:查询所有学生,把学生对应的班级也查询出来(一个学生对应一个班级)
(1)创建实体类
上篇文章已经创建过,Classes和Student类
(2)创建分解后的查询方法
在mapper下创建接口文件StudentMapper.java和ClassesMapper.java
ClassesMapper.java:
package com.first.mapper;
import com.first.pojo.Classes;
import org.apache.ibatis.annotations.Select;
public interface ClassesMapper {
//根据cid查询班级
@Select("select * from classes where cid= #{cid}")
Classes findByCid(int cid);
}
StudentMapper.java:
后面还得修改
package com.first.mapper;
import com.first.pojo.Student;
import org.apache.ibatis.annotations.Select;
import java.util.List;
public interface StudentMapper {
//查询所有学生信息
@Select("select * from student")
List findAll();
}
因为这个查询中student是主表,根据student表中的classId与classes表中的cid将两张表联系起来,所以classes表是从表,查询结果中除了有Student类中定义的普通属性外,还要有一个Classes的类对象!所以这就需要自定义映射关系!
(3)主表的查询配置自定义映射关系
StudentMapper.java:
package com.first.mapper;
import com.first.pojo.Student;
import org.apache.ibatis.annotations.One;
import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.Results;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.mapping.FetchType;
import java.util.List;
public interface StudentMapper {
//查询所有学生信息,所以classId也能够被查出来,虽然Student类中没有定义classId属性
@Select("select * from student")
//自定义映射关系
@Results(id = "studentMapper" ,value = {
@Result(id = true,property = "sid",column = "sid"),
@Result(property = "name",column = "name"),
@Result(property = "age",column = "age"),
@Result(property = "sex",column = "sex"),
@Result(property = "classes",column = "classId",
one = @One(select = "com.first.mapper.ClassesMapper.findByCid",
fetchType = FetchType.EAGER))
})
List findAll();
}
(4)测试
新建测试类TestManyTables
import com.first.mapper.StudentMapper;
import com.first.mapper.UserMapper;
import com.first.pojo.Student;
import com.first.pojo.User;
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.After;
import org.junit.Before;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
public class TestManyTables {
//全局变量
InputStream is=null;
SqlSession session =null;
StudentMapper userMapper =null;
//前置方法:测试类里的测试方法执行之前都会先执行前置方法
@Before
public void before() throws IOException {
//(1)读取核心配置文件
is= Resources.getResourceAsStream("SqlMapConfig.xml");
//(2)创建SqlSessionFactoryBuilder对象
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
//(3)SqlSessionFactoryBuilder对象获取SqlSessionFactory对象
SqlSessionFactory factory = builder.build(is);
//(4)SqlSessionFactory对象获取SqlSession对象
session = factory.openSession();
}
后置方法:测试类里的测试方法执行之后都会执行后置方法
@After
public void after() throws IOException {
//(7)释放资源
session.close();
is.close();
}
@Test
public void findAllStudent(){
//(5)SqlSession对象获取代理对象,即对应类的对象
StudentMapper studentMapper = session.getMapper(StudentMapper.class);
List all = studentMapper.findAll();
all.forEach(System.out::println);
}
}
输出:
Student{sid=1, name='张三', age=10, sex='男', classes=Classes{cid=1, className='三年一班', studentList=null}}
Student{sid=2, name='李四', age=10, sex='女', classes=Classes{cid=1, className='三年一班', studentList=null}}
Student{sid=3, name='尚尚', age=10, sex='男', classes=Classes{cid=2, className='三年二班', studentList=null}}
Student{sid=4, name='百战', age=11, sex='男', classes=Classes{cid=2, className='三年二班', studentList=null}}
Student{sid=5, name='王五', age=10, sex='男', classes=Classes{cid=2, className='三年二班', studentList=null}}
三.一对多关联查询
本例是查询所有班级,每个班级又对应多个学生,所以是一对多,班级表是主表,而学生表是从表。
(1)创建分解后的查询方法
在ClassesMapper.java中增加接口函数
后面还有修改,即(3)
//查询所有班级
@Select("select * from classes")
List findAll();
在StudentMapper.java中增加接口函数
//根据班级ID查询学生
@Select("select * from student where classId = #{cid}")
List findByClassId(int classId);
(2)主表的查询配置自定义映射关系
//查询所有班级
@Select("select * from classes")
@Results(id = "classMapper",value = {
@Result(id = true,property = "cid",column = "cid"),
@Result(property = "className",column = "className"),
//many:表示该属性是一个集合
@Result(property = "studentList",column = "cid",
many = @Many(select = "com.first.mapper.StudentMapper.findByClassId",
//一对多一般用延迟加载
fetchType = FetchType.LAZY))
})
List findAll();
(3)测试
//一对多
@Test
public void findAllClasses(){
ClassesMapper classesMapper = session.getMapper(ClassesMapper.class);
List all = classesMapper.findAll();
all.forEach(System.out::println);
}
输出:
[06/01 16:49:13] 867 [ main] DEBUG t.mapper.ClassesMapper.findAll - ==> Preparing: select * from classes
[06/01 16:49:13] 954 [ main] DEBUG t.mapper.ClassesMapper.findAll - ==> Parameters:
[06/01 16:49:14] 1292 [ main] DEBUG t.mapper.ClassesMapper.findAll - <== Total: 2
[06/01 16:49:14] 1295 [ main] DEBUG er.StudentMapper.findByClassId - ==> Preparing: select * from student where classId = ?
[06/01 16:49:14] 1295 [ main] DEBUG er.StudentMapper.findByClassId - ==> Parameters: 1(Integer)
[06/01 16:49:14] 1352 [ main] DEBUG er.StudentMapper.findByClassId - <== Total: 2
Classes{cid=1, className='三年一班', studentList=[Student{sid=1, name='张三', age=10, sex='男', classes=null}, Student{sid=2, name='李四', age=10, sex='女', classes=null}]}
[06/01 16:49:14] 1353 [ main] DEBUG er.StudentMapper.findByClassId - ==> Preparing: select * from student where classId = ?
[06/01 16:49:14] 1354 [ main] DEBUG er.StudentMapper.findByClassId - ==> Parameters: 2(Integer)
[06/01 16:49:14] 1359 [ main] DEBUG er.StudentMapper.findByClassId - <== Total: 3
Classes{cid=2, className='三年二班', studentList=[Student{sid=3, name='尚尚', age=10, sex='男', classes=null}, Student{sid=4, name='百战', age=11, sex='男', classes=null}, Student{sid=5, name='王五', age=10, sex='男', classes=null}]}
四.注解开发与映射文件开发的对比
注解开发更快,映射文件维护方便!
MyBatis 中更推荐使用映射文件开发, Spring 、 SpringBoot 更推荐注解方式。具体使用要视项目情况而定。它们的优点对比如下: 映射文件:- 代码与Sql语句是解耦的,修改时只需修改配置文件,无需修改源码。 因为注解当时修改sql语句后,java源码需要重新编译,但是映射文件方式直接修改即可!
- Sql语句集中,利于快速了解和维护项目。
- 级联查询支持连接查询和分解查询两种方式,注解开发只支持分解查询。
- 配置简单,开发效率高。
- 类型安全,在编译期即可进行校验,不用等到运行时才发现错误。
五.PageHelper分页插件
如果你也在用MyBatis,建议尝试该分页插件,这一定是最方便使用的分页插件。分页插件支持任何复杂的单表、多表分页。
开发过程中如果要进行分页查询,需要传入页数和每页条数。返回页面数据,总条数,总页数,当前页面,每页条数等数据。此时使用PageHelper插件可以快速帮助我们获取这些数据。
PageHelper是一款非常好用的开源免费的Mybatis第三方分页插件。使用该插件时,只要传入分页参数,即可自动生成页面对象。 我们使用该插件分页查询所有用户:
(1)引入依赖
在pom.xml文件中配置,配置完成后,刷新maven
com.github.pagehelper
pagehelper
5.3.0
(2)Mybatis配置文件中配置PageHelper插件
在SqlMapConfig.xml的
(3)使用PageHelper插件
在TestUserMapper.java中测试
//测试分页插件
@Test
public void testFindPage(){
//1.设置分页参数 参数一:起始页(此插件从1开始,而不是0);参数二:每页条数
PageHelper.startPage(1,3);
//2.正常查询
List all = userMapper.findAll();
//3.封装查询结果,生成页面对象
PageInfo pageInfo = new PageInfo(all);
//4.打印页面对象的属性
//是每页的结果集,而不是所有数据
System.out.println("结果集:"+pageInfo.getList());
System.out.println("总条数:"+pageInfo.getTotal());
System.out.println("总页数:"+pageInfo.getPages());
System.out.println("当前页:"+pageInfo.getPageNum());
System.out.println("每页条数:"+pageInfo.getSize());
}
输出:
[06/01 21:20:18] 2491 [ main] DEBUG apper.UserMapper.findAll_COUNT - ==> Preparing: SELECt count(0) FROM user
[06/01 21:20:18] 2576 [ main] DEBUG apper.UserMapper.findAll_COUNT - ==> Parameters:
[06/01 21:20:19] 2827 [ main] DEBUG apper.UserMapper.findAll_COUNT - <== Total: 1
[06/01 21:20:19] 2828 [ main] DEBUG com.first.mapper.UserMapper - Cache Hit Ratio [com.first.mapper.UserMapper]: 0.0
[06/01 21:20:19] 2828 [ main] DEBUG irst.mapper.UserMapper.findAll - ==> Preparing: select * from user LIMIT ?
[06/01 21:20:19] 2828 [ main] DEBUG irst.mapper.UserMapper.findAll - ==> Parameters: 3(Integer)
[06/01 21:20:19] 2843 [ main] DEBUG irst.mapper.UserMapper.findAll - <== Total: 3
结果集:Page{count=true, pageNum=1, pageSize=3, startRow=0, endRow=3, total=9, pages=3, reasonable=false, pageSizeZero=false}[User{id=1, username='小热', sex='男', address='北京'}, User{id=2, username='小巴', sex='男', address='上海'}, User{id=3, username='小赵', sex='女', address='广州'}]
总条数:9
总页数:3
当前页:1
每页条数:3
可以自己调整起始页参数和每页条数来测试一下!



