mybatis懒加载特性详解,以及多对多映射详解
来源:互联网 发布:淘宝网披肩女装 编辑:程序博客网 时间:2024/05/16 05:06
注意讲解都在代码中
准备数据库,测试数据,各位自己添加,因为是多对多,所以使用中间表:
用到的实体:
学生类:
public class Student { private Integer sid; private String name; private Integer age; //一个学生有多个老师,一个老师有多个学生 private List<Teacher> teachers=new ArrayList<Teacher>(); setter.. getter.... toString}
老师类:
public class Teacher { private Integer tid; private String tname; private String subject; //一个学生有多个老师,一个老师有多个学生 private List<Student> students=new ArrayList<Student>(); setter.. getter.... toString}
sql工具类:
package com.leige.test;import java.io.IOException;import java.io.InputStream;import org.apache.ibatis.io.Resources;import org.apache.ibatis.session.SqlSession;import org.apache.ibatis.session.SqlSessionFactory;import org.apache.ibatis.session.SqlSessionFactoryBuilder;/** * @author sqlsession工具类 * */public class SqlUtils { static SqlSessionFactory factory; //静态加载session工厂 static{ InputStream inputStream; try { inputStream = Resources.getResourceAsStream("com/leige/config/configuration.xml"); //1:实例化sqlsessionfactory工厂 factory= new SqlSessionFactoryBuilder().build(inputStream); } catch (IOException e) { } } public static SqlSession getSession() { try{ //开启session return factory.openSession(); }catch(Exception e){ throw new RuntimeException(e); } } /** * @param session * @param mapper * @return * 保证会话session一致,所以当做参数传过来 */ public static Object getmaMapper(SqlSession session,Class mapper){ //注册映射接口 factory.getConfiguration().addMapper(mapper); //返回操作实例 return session.getMapper(mapper); }}
全局配置不在全部贴出来了,需要说明的是,使用懒加载需要开启懒加载开关,还需要日志检测懒加载,还需要动态代理的cglib包,以及依赖包asm,和日志包
开启懒加载以及扫描包,自动分配名空间,在全局配置中需加入的配置
<!-- 首先在全局配置中配置支持懒加载 --> <settings> <setting name="lazyLoadingEnabled" value="true"/> <setting name="aggressiveLazyLoading" value="false"/> <setting name="logImpl" value="LOG4J"/> </settings> <typeAliases> <!-- 声明po类别名 --> <typeAlias alias="Student" type="com.leige.domain.Student"/><!-- 声明组合查询类 --> <!-- <typeAlias alias="StudentQueryVo" type="com.leige.domain.StudentQueryVo" /> <typeAlias alias="Teacher" type="com.leige.domain.Teacher"/> --><!-- 配置多个扫描,默认类的简单名称,不区分大小写 --> <package name="com.leige.domain"/> </typeAliases>
日志配置:
# Global logging configurationlog4j.rootLogger=DEBUG, stdout# MyBatis logging configuration...#log4j.logger.org.mybatis.example.BlogMapper=DEBUG# Console output...log4j.appender.stdout=org.apache.log4j.ConsoleAppenderlog4j.appender.stdout.layout=org.apache.log4j.PatternLayoutlog4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
Student接口映射:
<?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"><!-- 命名空间就是实现sql的隔离,把对于一个对象的操作sql语句放在一个命名空间中 这里的调用查询就是Student.selectStudentById --><mapper namespace="Student"><!-- 根据学生id查询学生信息及所有老师信息, 当然大家也可以不使用嵌套查询,也可以直接使用三表查询,效率较低,我是直接复制过来的注意sql小问题哦 SELECT student.*,teacher.* FROM student,t_s,teacher WHERE student.`sid`=t_s.`sid` AND teacher.`tid`=t_s.`tid` AND t_s.sid=1 --><!-- 定义结果map --> <resultMap type="Student" id="Student_Teacher"> <id column="sid" property="sid"/> <result column="name" property="name"/> <result column="age" property="age"/> <collection property="teachers" ofType="Teacher"> <!-- property表示集合属性,ofType表示集合类型 --> <id column="tid" property="tid"/> <result column="tname" property="tname"/> <result column="subject" property="subject"/> </collection> <!-- association的使用和collection类似,多用于一对一映射或者一对多一方的resultMap的输出映射 <association property=""></association> --> </resultMap> <!-- 懒加载 ,由于是多对多,所以需要加查询中间表,所以,不能直接使用单表id查询--><select id="selectStudentLazy" parameterType="int" resultType="Student" > <![CDATA[ SELECT student.* FROM student,t_s WHERE t_s.sid=student.sid AND t_s.tid=#{value} ]]></select><!-- 多对多级联查询,其实个人感觉,mybatis的映射关系主要体现在数据库设计和sql语法上面如果数据库基础知识过硬,没必要花费时间去学习 --><select id="select_student_teacher" parameterType="int" resultMap="Student_Teacher"> <![CDATA[ SELECT tt.*,teacher.`tname`,teacher.`subject` FROM teacher, (SELECT student.*,t_s.`tid` FROM student,t_s WHERE student.`sid`=t_s.`sid`) tt WHERE tt.tid=teacher.`tid` AND sid=#{value} ]]></select></mapper>
Teacher接口映射,大家可以对比下,使用懒加载和未使用懒加载时resultMap的区别,仔细思考就会发现其实很简单
<?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="Teacher"><!-- 未使用懒加载时的resultMap --> <resultMap type="Teacher" id="Teacher_Student"> <id column="tid" property="tid"/> <result column="tname" property="tname"/> <result column="subject" property="subject"/> <collection property="students" ofType="Student"> <!-- property表示集合属性,ofType表示集合类型 --> <id column="sid" property="sid"/> <result column="name" property="name"/> <result column="age" property="age"/> </collection> <!-- association的使用和collection类似,多用于一对一映射或者一对多一方的resultMap的输出映射 <association property=""></association> --> </resultMap> <select id="selectTeahcerById" parameterType="int" resultType="Teacher" > <![CDATA[ select * from teacher where id=#{value} ]]> </select> <!-- 未使用懒加载时,联合查询关键是sql语句的调优, 这里简单介绍一下mybatis的对象映射关系,其实学习mybatis的对象映射,个人大家不必花费时间去学习, 因为都是相通的,主要是数据库表的设计,具体的查询映射,主要体现在sql语法上,数据库知识过硬,没有学习的必要, 这里由于本人数据库知识有限,抱歉没有优化,能查出来,我就很高兴了 当然大家不使用嵌套查询,也可以直接使用三表查询,效率较低 SELECT student.*,teacher.* FROM student,t_s,teacher WHERE student.`sid`=t_s.`sid` AND teacher.`tid`=t_s.`tid` AND t_s.sid=1 --> <select id="selectNoLazy" parameterType="int" resultMap="Teacher_Student"> <![CDATA[ SELECT tt.*,student.name,student.age FROM (SELECT teacher.*,t_s.sid FROM teacher,t_s WHERE teacher.tid=t_s.tid) tt,studentWHERE tt.sid=student.sid AND tid=#{value} ]]> </select> <!-- mybatis使用懒加载需使用resultMap,在resultMap中有collections和associatation标签都支持懒加载resultType不可以将属性列和集合映射,所以需要使用resultMap这里最重要的就是懒加载的实现,mybatis对于懒加载的实现就是延迟使用子查询的发出,这与hibernate的机制是一样的所以子查询是懒加载的灵魂,下面是定义懒加载的resultMap,懒加载和非懒加载的resultMap的区别就是关联映射使用的是子查询,子查询调用的时外部Student中的懒加载子查询,需要加上命名空间 --> <resultMap type="Teacher" id="Teacher_Student_lazy"> <id column="tid" property="tid"/> <result column="tname" property="tname"/> <result column="subject" property="subject"/> <!-- select:基于column列发出的子查询语句,即SELECT student.* FROM student where sid=?; column:就是与select相关联的另一个表中的列 例如这里完整的查询是: 父查询 SELECT * FROM teacher WHERE tid=? 子查询根据父查询的tid再去查询学生表,因为是多对多,所以需要查询中间表 SELECT student.* FROM student,t_s WHERE t_s.sid=student.sid AND t_s.tid=#{value}--> <collection property="students" ofType="Student" select="Student.selectStudentLazy" column="tid" > <!-- 用于懒加载关联的查询 --> </collection> </resultMap> <select id="selectTeacherLazy" parameterType="int" resultMap="Teacher_Student_lazy"><!-- 由于这是多对多映射,所以查询多关联关系,需要借助中间表,所以使用resultMap --> <![CDATA[ select * from teacher where tid=#{value} ]]> </select> </mapper>
多对多映射详解
这里简单介绍一下mybatis的对象映射关系,其实学习mybatis的对象映射,个人大家不必花费时间去学习,
因为都是相通的,主要是数据库表的设计,具体的查询映射,主要体现在sql语法上,数据库知识过硬,没有学习的必要,多对多映射的解释请查看测试代码具体感受下:
测试代码
package com.leige.test;import org.apache.ibatis.session.SqlSession;import org.junit.Test;import com.leige.domain.Student;import com.leige.domain.Teacher;public class App2 { @Test public void testSelectLazy(){ //获取session SqlSession session=SqlUtils.getSession(); //查询 Teacher teacher=session.selectOne("Teacher.selectTeacherLazy", 1); //打印 //测试懒加载时可以在此处打断点,就会发现只有在使用子集合时才会加载 System.out.println(teacher); //真正加载的位置 System.out.println(teacher.getStudents()); } /** * 测试立即加载,实现多对多,获取实现 */ @Test public void testSelectNoLazy(){ //获取session SqlSession session=SqlUtils.getSession(); /*//根据id查询老师信息,以及老师教的所有学生的信息, 当然这种例子是不合理的,现实中要么是学生单项关联老师, 或者以班级为单位,老师学生都关联班级,但是这里只是演示多对多以及懒加载,至于对象和具体问题的处理还需要大家自己设计*/ Teacher teacher=session.selectOne("Teacher.selectNoLazy", 1); //打印 System.out.println(teacher); System.out.println(teacher.getStudents()); System.out.println("---------------------------我是分割线-------------------"); //根据学生id查询学生信息,以及学生的所有老师信息 Student student=session.selectOne("Student.select_student_teacher",1); //输出 System.out.println(student); System.out.println(student.getTeachers()); }}
懒加载日志显示:
一级查询
懒加载查询
0 0
- mybatis懒加载特性详解,以及多对多映射详解
- Mybatis中多对多映射详解
- mybatis关系映射之一对多和多对一详解
- Mybatis中一对多映射详解
- JAVAWEB开发之mybatis详解(二)——高级映射、查询缓存、mybatis与Spring整合以及懒加载的配置和逆向工程
- JAVAWEB开发之mybatis详解(二)——高级映射、查询缓存、mybatis与Spring整合以及懒加载的配置和逆向工程
- 关系映射多对多详解
- 【Hibernate步步为营】--多对多映射详解
- Hibernate 多对多关系映射详解
- 【Hibernate步步为营】--多对多映射详解
- Hibernate映射详解(五)--多对多关联映射 .
- Hibernate对象关系映射详解之一对多关系映射
- mybatis--映射文件详解
- MyBatis:多对一表关系详解
- Mybatis映射关系-多对一映射
- Mybatis的一对多,多对一以及延迟加载
- Mybatis的一对多,多对一以及延迟加载
- Mybatis 延迟加载详解
- 历史版本的CentOS软件包
- WebRTC VideoEngine综合应用示例(一)——视频通话的基本流程
- iOS原生二维码加logo模糊
- linux 下利用 crontab 备份mysql
- 第九周项目1--深复制体验
- mybatis懒加载特性详解,以及多对多映射详解
- 搭建struts2开发环境
- Android 自定义变化的文本控件ColorChangeView
- 更方便的使用retrofit2,兼容retrofit1.x
- 不为测试而测试
- Redis Notes
- MultipartEntity 和 UrlEncodedFormEntity || application/x-www-form-urlencoded 和 multipart/form-data
- ]MySQL操作命令语句实例
- launcher点击,加载,拖动图标过程三