MyBatis学习总结(5)— 多对一、一对多的问题
1. 多对一
多个对象对应一个对象
比如:你们都是我的学生 ,多个学生对应一个老师
掌握两个单词:
-
association — 联系 ,关联 多个人可以关联一个人。
-
collection — 集合 一个人有一个集合,包含多个人。
-
发现是多对一业务情况,我们需要使用association 标签进行关联
要求:
根据给出的数据库,数据库有两个表student和teacher,student中多个学生对应teacher中的同一个老师。要求查询出表中的所有学生,并查出每个学生对应的同一个老师。
数据库信息如下:
Student表格:
Teacher表格:
1.1. 多对一的处理方式一
思想:数据库连表查询
使用数据库的思想处理:联表查询
-
1.定义dao接口
List<Student> getStudents();
-
2.Student实体类
//student实体类的变量 private int id; private String name; Teacher teacher; //对应数据库的tid,对应teacher表的id
-
3.编写查询语句
-
查询学生信息 id name tid , 由于我们要得到老师的信息,我们需要联表查询
-
查询老师的信息 id name 。
StudentMapper.xml
:<?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对应Mapper接口的类--> <mapper namespace="org.xiao.dao.StudentMapper"> <!--<!–解决问题方式一:按查询结果嵌套处理,模拟数据库思想;–>--> <select id="getStudents" resultMap="ST"> select * from mybatis.student </select> <!--column="数据库的列名" property="类变量名"--> <resultMap id="ST" type="Student"> <id column="id" property="id"/> <result column="name" property="name"/> <!--属性和字段对应 , 类和表对应 , 对象和记录 关联一个字段 需求:拿到老师这个类的属性 association : 关联,多对一 column : 数据库对应的列名 property : 对应属性名 javaType : 多对一字段对应的Java类型 select : 关联一个语句 --> <!--连接Teacher表--> <association column="tid" property="teacher" javaType="Teacher" select="getTeacher"/> </resultMap> <!--查询老师信息--> <select id="getTeacher" resultType="Teacher"> select * from mybatis.teacher where id = #{id} </select> </mapper>
-
-
3.测试类
package org.xiao.dao; import org.apache.ibatis.session.SqlSession; import org.junit.Test; import org.xiao.pojo.Student; import org.xiao.utils.MyBatisUtils; import java.util.List; public class StudentDaoTest { @Test public void getStudents(){ SqlSession sqlSession = MyBatisUtils.getSqlSession(); StudentMapper mapper = sqlSession.getMapper(StudentMapper.class); List<Student> students = mapper.getStudents(); for (Student student : students) { System.out.println(student.getName()+"----"+student.getTeacher().getName()); } } }
-
项目结构
说明:代码的其他部分参考前几篇博客,pom.xml、log4j、database,utils等的配置。
-
结果
1.2 多对一的处理方式二
思想:面向对象
一个resultMap解决 , 模拟面向对象的思想
-
1.编写接口
List<Student> getStudentsTwo();
-
2.编写处理的mapper映射文件,
StudentMapper.xml
-
查询学生id,学生姓名,老师姓名,需要从学生表和老师表中查询
-
学生对应的类进行映射,发现老师一个对象 , 所以关联一个对象;
<select id="getStudentsTwo" resultMap="ST2"> select s.id,s.name,t.name as tname from mybatis.student as s ,mybatis.teacher as t where s.tid = t.id </select> <!--设置结果集映射ResultMap --> <resultMap id="ST2" type="Student"> <id property="id" column="id"/> <result property="name" column="name"/> <!--直接关联一个老师--> <association property="teacher" javaType="Teacher"> <result property="name" column="tname"/> </association> </resultMap>
-
-
3.测试类
package org.xiao.dao; import org.apache.ibatis.session.SqlSession; import org.junit.Test; import org.xiao.pojo.Student; import org.xiao.utils.MyBatisUtils; import java.util.List; public class StudentDaoTestTwo { @Test public void getStudentsTwo(){ SqlSession sqlSession = MyBatisUtils.getSqlSession(); Object mapper = sqlSession.getMapper(StudentMapper.class); List<Student> students = ((StudentMapper) mapper).getStudentsTwo(); for (Student student : students) { System.out.println(student.getName()+"----"+student.getTeacher().getName()); } } }
-
结果:
1.3 总结
-
mybatis中遇到多对一的情况,要使用关联映射处理:使用
association
association : 关联,多对一 column : 数据库对应的列名 property : 对应属性名 javaType : 多对一字段对应的Java类型 select : 关联一个语句
-
两种处理思路:
- 数据库思想 : 联表查询
- OOP思想 :关联对象
2. 一对多
一个老师对应多个学生,根据老师的id查询老师,以及这位老师对应的所有学生。
一对多的业务:使用collection
处理
-
环境搭建
Teacher实体类
private int id; private String name; //一个老师对应多个学生 private List<Student> students;
2.1 一对多处理方式一
思想:数据库连表查询
-
1.定义dao接口
Teacher getTeacher(int id);
-
2.查询语句
-
查询老师信息 id name , 由于我们要得到学生的信息,我们需要联表查询
-
查询学生的信息 tid id name 。
<?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对应Mapper接口的类--> <mapper namespace="org.xiao.dao.TeacherMapper"> <!-- 数据库思想 --> <!-- 根据id 先查询老师 --> <select id="getTeacher" resultMap="TS"> select * from mybatis.teacher where id = ${id} </select> <!--连接student表--> <resultMap id="TS" type="Teacher"> <collection property="students" javaType="ArrayList" ofType="Student" column="id" select="getStudent"/> </resultMap> <!--查询学生信息--> <select id="getStudent" resultType="Student"> select * from mybatis.student where tid = #{id} </select> </mapper>
-
-
3.测试类
public class TeacherDaoTest { @Test public void getTeacher(){ SqlSession sqlSession = MyBatisUtils.getSqlSession(); TeacherMapper mapper = sqlSession.getMapper(TeacherMapper.class); Teacher teacher = mapper.getTeacher(1); System.out.println(teacher.getName()); System.out.println(teacher.getStudents()); } }
-
结果:
2.2 一对多处理方式二
思想:面向对象
-
1.编写接口
Teacher getTeacherTwo(int id);
-
2.编写处理的mapper映射文件,
TeacherMapper.xml
-
查询老师姓名,老师id,学生姓名,学生id,需要从老师表和学生表中查询
-
老师对应的类进行映射,发现学生一个对象 , 所以关联一个对象;
<?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对应Mapper接口的类--> <mapper namespace="org.xiao.dao.TeacherMapper"> <!-- 面向对象思想--> <!--查询老师信息、学生信息--> <select id="getTeacherTwo" resultMap="TS2"> select s.id sid,s.name sname,t.name tname,t.id tid from mybatis.teacher t ,mybatis.student s where s.tid = t.id = #{id} </select> <!--老师类关联学生类--> <resultMap id="TS2" type="Teacher"> <result property="name" column="tname"/> <collection property="students" ofType="Student"> <id property="id" column="sid"/> <result property="name" column="sname"/> <result property="tid" column="tid"/> </collection> </resultMap> </mapper>
-
-
3.测试类
@Test public void getTeacherTwo(){ SqlSession sqlSession = MyBatisUtils.getSqlSession(); TeacherMapper mapper = sqlSession.getMapper(TeacherMapper.class); Teacher teacher2 = mapper.getTeacherTwo(1); System.out.println(teacher2.getName()); System.out.println(teacher2.getStudents()); }
-
结果:
3. 总结
-
关联映射处理
多对一:association 关联
一对多:collection 集合
-
两种解决方式:
面对对象的思想:关联对象
SQL语句思想:联表查询