Mybatis的多表模型
4.2 多表模型一对一操作
-
一对一模型: 人和身份证,一个人只有一个身份证
步骤:
- 在Card类要有person属性,得到数据好封装。
- 返回结果集天然不带有封装类的关系。我们要重新声明结果集。
- 测试。
代码实现
- 步骤一: sql语句准备
|
|
相关实体类:
|
|
//一对一查询 select * from card c,person p where c.pid = p.id
-
实体关联属性
-
配置结果集
-
测试
-
步骤二:配置文件
|
|
- 步骤三:测试类
|
|
一对一配置总结:
4.3 多表模型一对多操作
-
一对多模型: 一对多模型:班级和学生,一个班级可以有多个学生。
![image-20210330154023544](D:\Wechat\WeChat Files\wxid_d97ib7s1lsxa22\FileStorage\File\2023-09\img\image-20210330154023544.png)
准备资料和步骤:
- 数据创建两张表:student classes 。创建两个bean实体类。
- 在班级表中设置学生列表属性。
- 映射配置文件配置结果集。
- 测试。
代码实现
- sql语句准备
|
|
- 创建bean文件。
|
|
-
创建一个一对多mapper文件,创建一个同名mapper.xml映射文件。
1 2 3 4
public interface OneToManyMapper { //查询全部 public abstract List<Classes> selectAll(); }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
<?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.itgaohe.mapper.ClassesMapper"> <resultMap id="oneToMany" type="com.itgaohe.pojo.Classes"> <id property="id" column="cid"/> <result property="name" column="cname"/> <!-- collection :集合映射标签 property:实体类中属性名 ofType:集合属性的每一个元素的类型 --> <collection property="students" ofType="com.itgaohe.pojo.Student"> <id property="id" column="sid"/> <result property="name" column="sname"/> <result property="age" column="sage"/> </collection> </resultMap> <select id="selectAll" resultMap="oneToMany"> SELECT c.id cid,c.name cname,s.id sid,s.name sname,s.age sage FROM classes c,student s WHERE c.id=s.cid </select> </mapper>
-
在主配置文件中进行别名、mapper配置。
![image-20210329153710595](D:\Wechat\WeChat Files\wxid_d97ib7s1lsxa22\FileStorage\File\2023-09\img\image-20210329153710595.png)
-
测试类
|
|
运行结果:
运行结果为如下:
|
|
3.一对多配置文件总结:
|
|
tips: 常见问题:属性值问题
数据库名称、bean、映射配置名称在拷贝代码的时候容易不一致
4.4 多表模型多对多操作
-
多对多模型:学生和课程,一个学生可以选择多门课程、一个课程也可以被多个学生所选择。
![image-20210330160220739](D:\Wechat\WeChat Files\wxid_d97ib7s1lsxa22\FileStorage\File\2023-09\img\image-20210330160220739.png)
准备资料和步骤:
-
数据创建三张表:student\course\stu_cr。
-
创建两个bean文件。
-
创建一个一对多mapper文件,创建一个同名mapper.xml映射文件。
-
在主配置文件中进行别名、mapper配置。
-
开始编写mapper代码及相关功能功能。测试。
-
-
代码实现
-
步骤一: sql语句准备
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
CREATE TABLE course( id INT PRIMARY KEY AUTO_INCREMENT, NAME VARCHAR(20) ); INSERT INTO course VALUES (NULL,'语文'); INSERT INTO course VALUES (NULL,'数学'); CREATE TABLE stu_cr( id INT PRIMARY KEY AUTO_INCREMENT, sid INT, cid INT, CONSTRAINT sc_fk1 FOREIGN KEY (sid) REFERENCES student(id), CONSTRAINT sc_fk2 FOREIGN KEY (cid) REFERENCES course(id) ); INSERT INTO stu_cr VALUES (NULL,1,1); INSERT INTO stu_cr VALUES (NULL,1,2); INSERT INTO stu_cr VALUES (NULL,2,1); INSERT INTO stu_cr VALUES (NULL,2,2); SELECT s.id sid,s.`NAME` sname,c.`NAME` cname FROM student s,stu_cr cr,course c WHERE s.`id` = cr.sid AND cr.cid = c.id
-
接口方法
-
步骤二:配置文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
<?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.itgaohe.mapper.StudentMapper"> <resultMap id="manyToMany" type="com.itgaohe.pojo.Student"> <id column="sid" property="id"/> <result column="sname" property="name"/> <result column="sage" property="age"/> <collection property="courses" ofType="com.itgaohe.pojo.Course"> <id column="cid" property="id"/> <result column="cname" property="name"/> </collection> </resultMap> <!-- public List<StudentMapper> selectAll();--> <select id="selectAll" resultMap="manyToMany"> SELECT sc.sid,s.name sname,s.age sage,sc.cid,c.name cname FROM student s,course c,stu_cr sc WHERE sc.sid=s.id AND sc.cid=c.id </select> </mapper>
-
步骤三:测试类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
@Test public void selectAll() throws Exception{ //1.加载核心配置文件 InputStream is = Resources.getResourceAsStream("MyBatisConfig.xml"); //2.获取SqlSession工厂对象 SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is); //3.通过工厂对象获取SqlSession对象 SqlSession sqlSession = sqlSessionFactory.openSession(true); //4.获取ManyToManyMapper接口的实现类对象 ManyToManyMapper mapper = sqlSession.getMapper(ManyToManyMapper.class); //5.调用实现类的方法,接收结果 List<Student> students = mapper.selectAll(); //6.处理结果 for (Student student : students) { System.out.println(student.getId() + "," + student.getName() + "," + student.getAge()); List<Course> courses = student.getCourses(); for (Course cours : courses) { System.out.println("\t" + cours); } } //7.释放资源 sqlSession.close(); is.close(); }
运行效果:
![image-20210329212531848](D:\Wechat\WeChat Files\wxid_d97ib7s1lsxa22\FileStorage\File\2023-09\img\image-20210329212531848.png)
-
3.多对多配置文件总结:
|
|
4.5 多表模型操作总结
|
|
注解开发略。
-
注解实现crud。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
/*查询*/ @Select("select * from student where id = #{id} or name = #{name}") List<Student> findbyId(@Param("id") Integer id, @Param("name")String name); /*新增*/ @Options(useGeneratedKeys = true,keyColumn = "id" ,keyProperty = "id") @Insert("insert into student (id,name,age,cid) values(null,#{name},#{age},#{cid})") void add(Student student); /*修改*/ @Update("update student set name = #{name},age= #{age},cid = #{cid} where id = #{id}") void update(Student student); /*删除*/ @Delete("delete from student where id = #{id}") void delete(Integer id);
-
注解实现1对1。
1 2 3 4 5 6 7 8 9 10 11 12
@Results({ @Result(property = "id",column = "id"), @Result(property = "number",column = "number"), @Result( property = "p", javaType = Person.class, column = "pid", one = @One(select = "com.itgaohe.mapper.PersonMapper.findById") ) }) @Select("select * from card where id = #{id}") public Card findById(Integer id);
1 2
@Select("select * from person where id = #{id}") public Person findById(Integer id);
-
注解实现1对多。
1 2 3 4 5 6 7 8 9 10 11 12
@Results({ @Result(property = "id",column = "id"), @Result(property = "name",column = "name"), @Result( property = "students",/*实体对象属性名*/ javaType = List.class,/*查询结果封装类型*/ column = "id",/*查询参数*/ many = @Many(select = "com.itgaohe.mapper.StudentMapper.findByCourseId") ) }) @Select("select * from course") public List<Course> findById(Integer id);
1 2 3 4
@Select("SELECT s.id,s.name,s.age,s.cid FROM student s,stu_cr cr " + "WHERE cr.cid = #{id} " + "AND cr.sid = s.id") List<Student> findByCourseId(Integer id);
分页查询
三. 分页插件
以前我们都是findAll()查询。
问题:数据量一旦大了,查询效率会非常慢。页面展示渲染更需要大量时间。
所以在企业应用中展示条形数据,几乎都是分页。
3.1 分页插件介绍
- 分页可以将很多条结果进行分页显示。
- 如果当前在第一页,则没有上一页。如果当前在最后一页,则没有下一页。
- 需要明确当前是第几页,这一页中显示多少条结果。
- MyBatis分页插件总结
- 在企业级开发中,分页也是一种常见的技术。而目前使用的 MyBatis 是不带分页功能的,如果想实现分页的 功能,需要我们手动编写 LIMIT 语句。但是不同的数据库实现分页的 SQL 语句也是不同的,所以手写分页 成本较高。这个时候就可以借助分页插件来帮助我们实现分页功能。
- PageHelper:第三方分页助手。将复杂的分页操作进行封装,从而让分页功能变得非常简单。
3.2 分页插件的使用
MyBatis可以使用第三方的插件来对功能进行扩展,分页助手PageHelper是将分页的复杂操作进行封装,使用简单的方式即可获得分页的相关数据
开发步骤:
- 导入与PageHelper的jar包
- 在mybatis核心配置文件中配置PageHelper插件
- 测试分页数据获取
代码演示:
①导入与PageHelper的jar包
|
|
②在mybatis核心配置文件中配置PageHelper插件
|
|
③测试分页数据获取
|
|
3.3 分页插件的参数获取
获得分页相关的其他参数:
|
|
3.2-3.3演示:
|
|
演示效果;
![image-20210329140304948](D:\Wechat\WeChat Files\wxid_d97ib7s1lsxa22\FileStorage\File\2023-09\img\image-20210329140304948.png)
3.4 分页插件知识小结
分页:可以将很多条结果进行分页显示。
-
分页插件 jar 包: pagehelper-5.1.10.jar jsqlparser-3.1.jar
-
:集成插件标签。 -
分页助手相关 API
1.PageHelper:分页助手功能类。
- startPage():设置分页参数
- PageInfo:分页相关参数功能类。
- getTotal():获取总条数
- getPages():获取总页数
- getPageNum():获取当前页
- getPageSize():获取每页显示条数
- getPrePage():获取上一页
- getNextPage():获取下一页
- isIsFirstPage():获取是否是第一页
- isIsLastPage():获取是否是最后一页
二级缓存
一级缓存:
一级缓存基于sqlSession默认开启,在操作数据库时需要构造SqlSession对象,在对象中有一个HashMap用于存储缓存数据。不同的SqlSession之间的缓存数据区域是互相不影响的。
-
如果SqlSession执行了DML操作(增删改),并且提交到数据库,MyBatis则会清空SqlSession中的一级缓存,这样做的目的是为了保证缓存中存储的是最新的信息,避免出现脏读现象。
-
sqlSession关闭。
二级缓存
mapper级别的缓存,多个SqlSession去操作同一个Mapper的sql语句,多个SqlSession去操作数据库得到数据会存在二级缓存区域,多个SqlSession可以共用二级缓存,二级缓存是跨SqlSession的。
- 手动开启
- 面向所有的sqlSession
- 性能提升(弊大于利)
的区别
二级缓存需要手动打开 打开总开关: 在核心配置文件SqlMapConfig.xml中加入
< !–注意顺序–> < setting name=“cacheEnabled” value=“true”/>
|
|