目录

一.二级缓存

二.一对一关联查询

三.一对多关联查询

四.注解开发与映射文件开发的对比

五.PageHelper分页插件


一.二级缓存

MyBatis默认开启一级缓存,接下来我们学习如何在注解开发时使用二级缓存:
1
(1)POJO类实现Serializable接口。
(2)在MyBatis配置文件添加如下设置:
下面的这个配置其实可以不加,因为这个配置默认就是true
在核心配置文件的<configuration>的中添加如下配置
    <settings><setting name="cacheEnabled" value="true"/></settings>
(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 {//前置方法:测试类里的测试方法执行之前都会先执行前置方法@Testpublic 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对象操作数据库时才能共享一级缓存;要是同一个工厂对象创建的SqlSession,在进行查询时都能共享数据。一般在项目中只有一个SqlSessionFactory对象, 所以二级缓存的数据是全项目共享的。所以session1和session2共享二级缓存,而不共享一级缓存*/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<Student> 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"),/*property:属性名column:调用从表方法时传入的参数列,因为学生表需要将classId传到班级表中,去匹配班级表的cidone:表示该属性是一个对象,查看Student类可知classes是Classes类的一个对象select:调用的从表(这里的从表是班级表)方法fetchType: 加载方式,一对一一般为立即加载*/@Result(property = "classes",column = "classId",one = @One(select = "com.first.mapper.ClassesMapper.findByCid",fetchType = FetchType.EAGER))})List<Student> 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;//前置方法:测试类里的测试方法执行之前都会先执行前置方法@Beforepublic 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();}后置方法:测试类里的测试方法执行之后都会执行后置方法@Afterpublic void after() throws IOException {//(7)释放资源session.close();is.close();}@Testpublic void findAllStudent(){//(5)SqlSession对象获取代理对象,即对应类的对象StudentMapper studentMapper = session.getMapper(StudentMapper.class);List<Student> 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<Classes> findAll();

在StudentMapper.java中增加接口函数

//根据班级ID查询学生
@Select("select * from student where classId = #{cid}")
List<Student> 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<Classes> findAll();

(3)测试

//一对多
@Test
public void findAllClasses(){ClassesMapper classesMapper = session.getMapper(ClassesMapper.class);List<Classes> 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

        <!-- PageHelper --><dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper</artifactId><version>5.3.0</version></dependency>

(2)Mybatis配置文件中配置PageHelper插件

在SqlMapConfig.xml的<configuration>中添加如下代码

    <plugins><plugin interceptor="com.github.pagehelper.PageInterceptor"><!--设置数据库类型,必须设置,因为不同数据库的分页sql不同--><property name="helperDialect" value="mysql"/></plugin></plugins>

(3)使用PageHelper插件

在TestUserMapper.java中测试

    //测试分页插件@Testpublic void testFindPage(){//1.设置分页参数 参数一:起始页(此插件从1开始,而不是0);参数二:每页条数PageHelper.startPage(1,3);//2.正常查询List<User> 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

可以自己调整起始页参数和每页条数来测试一下!

MyBatis入门(九)注解开发(下) PageHelper分页插件相关推荐

  1. SpringBoot入门篇--整合mybatis+generator自动生成代码+druid连接池+PageHelper分页插件

    我们这一一篇博客讲的是如何整合Springboot和Mybatis框架,然后使用generator自动生成mapper,pojo等文件.然后再使用阿里巴巴提供的开源连接池druid,这个连接池的好处我 ...

  2. springboot2.0.5集成mybatis(PageHelper分页插件、generator插件使用)

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/zab635590867/article ...

  3. Springboot 系列(十二)使用 Mybatis 集成 pagehelper 分页插件和 mapper 插件

    前言 在 Springboot 系列文章第十一篇里(使用 Mybatis(自动生成插件) 访问数据库),实验了 Springboot 结合 Mybatis 以及 Mybatis-generator 生 ...

  4. MyBatis-学习笔记04【04.自定义Mybatis框架基于注解开发】

    Java后端 学习路线 笔记汇总表[黑马程序员] MyBatis-学习笔记01[01.Mybatis课程介绍及环境搭建][day01] MyBatis-学习笔记02[02.Mybatis入门案例] M ...

  5. spring boot整合mybatis+通用mapper+pagehelper分页插件

    spring boot整合mybatis+通用mapper+pagehelper分页插件 pom依赖 <?xml version="1.0" encoding="U ...

  6. spring boot+mybatis+thymeleaf+pagehelper分页插件实现分页功能

    文章目录 前言 正文 业务场景 后端 pom.xml application.yml 实体类video.java和User.java----映射VideoMapper.xml----VideoMapp ...

  7. Spring boot 实战指南(二):Mybatis、动态绑定、多数据源、分页插件、Mybatis-Plus

    文章目录 一.整合Mybatis 1.搭建数据库环境 2.基于注解整合Mybatis (1)创建项目 (2)具体代码实现 (3)测试 3.基于xml整合Mybatis 4.Mybatis的动态SQL ...

  8. PageHelper 分页插件使用总结

    一个简洁的博客网站:http://lss-coding.top,欢迎大家来访 学习娱乐导航页:http://miss123.top/ 一.认识 PageHelper **官网:**https://pa ...

  9. PageHelper分页插件及PageInfo介绍及使用

    1. MyBatis分页插件-PageHelper的配置 maven配置文件pom.xml 引入依赖: <!--引入PageHelper分页插件 → PageHelper--><de ...

最新文章

  1. wcf系列---- binding的使用(1)
  2. Java程序员从笨鸟到菜鸟之(九十一)跟我学jquery(七)jquery动画大体验
  3. java动态拼接String类sql
  4. python进程、线程、协程
  5. pom.xml的配置详解
  6. [密码学基础][每个信息安全博士生应该知道的52件事][Bristol Cryptography][第32篇]基于博弈的证明和基于模拟的证明
  7. 电气工程及其自动化学不学c语言,电气工程及其自动化学什么 就业方向有哪些...
  8. javascript的list循环
  9. LeetCode(509)——斐波那契数(JavaScript)
  10. 使用python将数据存入SQLite3数据库
  11. 伯克利人工智能导论课开放:视频、PPT和练习都在这 | 资源
  12. windows下运行python打印有颜色的字_Windows和Linux下Python输出彩色文字的方法教程...
  13. Fizz Gateway API in Java
  14. POJ1741 点分治模板
  15. django html中文乱码,如何使用Python/Django执行HTML解码/编码?
  16. 单片机51keil编程流程
  17. java 气象数据_科学网-下载某地历史逐小时环境气象数据的方法-风速风向温湿度-洪晓强的博文...
  18. JAVA 实现阿里云的短信验证码
  19. Excel - SUM和ABS函数联合使用
  20. idea html设置字体大小,intellij idea设置(字体大小、背景)

热门文章

  1. 金,银,铜,铝nbsp;的导电性能
  2. wiz文件打开方式(只要notepad++即可)
  3. 蓝牙MESH 官方文档解读 翻译(1)
  4. qmake和nmake
  5. 3DS MAX分配网格时出错,减少面数以渲染此场景
  6. 关于NX二次开发嵌入MFC的相关入门
  7. 博睿数据2021战略发布巡展,开辟IT运维创新路径
  8. SLAM踩坑| 对‘pcl::console::print(pcl::console::VERBOSITY_LEVEL, char const*, ...)’未定义的引用
  9. linux bzip2 1.06.tar.gz,Linux06 文件的打包和压缩(gzip/gunzip、tar、bzip2)
  10. 全国降雨侵蚀力因子R值计算教程