文章目录
9.多对一处理
多个对象对应一个对象
比如:多个学生对应一个老师
掌握两个单词:
- association — 联系 ,关联 多个人可以关联一个人。
- collection — 集合 一个人有一个集合,包含多个人。
- 发现是多对一业务情况,我们需要使用association 标签进行关联
准备工作:在数据库中创建要测试的数据表
先建立一个mybatis的数据库,在数据库中建立两个关联的表
CREATE TABLE `teacher` (
`id` INT(10) NOT NULL,
`name` VARCHAR(30) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8
INSERT INTO teacher(`id`,`name`) VALUES (1,'秦老师');
CREATE TABLE `student` (
`id` INT(10) NOT NULL,
`name` VARCHAR(30) DEFAULT NULL,
`tid` INT(10) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `fktid` (`tid`),
CONSTRAINT `fktid` FOREIGN KEY (`tid`) REFERENCES `teacher` (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8
结果显示如下表:
通过tid进行关联连接
多对一的处理方式一:
使用数据库的思想处理:联表查询
1. 创建实体类
在idea中根据数据表和测试所需环境(多对一)创建对应的实体类
Student类
package com.westos.pojo;
public class Student {
private int id;
private String name;
private Teacher teacher;
public Student() {
}
public Student(int id, String name, Teacher teacher) {
this.id = id;
this.name = name;
this.teacher = teacher;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Teacher getTeacher() {
return teacher;
}
public void setTeacher(Teacher teacher) {
this.teacher = teacher;
}
@Override
public String toString() {
return "Student{" +
"id=" + id +
", name='" + name + '\'' +
", teacher=" + teacher +
'}';
}
}
Teacher类
package com.westos.pojo;
public class Teacher {
private int id;
private String name;
public Teacher() {
}
public Teacher(int id, String name) {
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Teacher{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
2. 定义dao接口
package com.westos.dao;
import com.westos.pojo.Student;
import java.util.List;
public interface StudentDao {
//获得全部学生的信息以及对应的老师
List<Student> getStudents();
}
2. 对应接口配置文件StudentMapper.xml
编写查询语句
- 查询学生信息 id name tid , 由于我们要得到老师的信息,我们需要联表查询
- 查询老师的信息 id name 。
遇到的问题:学生类中关联老师,多个学生对应一个老师,学生类属性中有一个特殊属性teacher,他对应的是一个表,而不是一条记录。无法直接查询。
关键字:
- association :关联,多对一
- column:数据库对应的列名
- property:对应属性名
- javaType:多对一字段对应的java类型
- select;关联一个语句
<?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="com.westos.dao.StudentDao">
<!--遇到问题:学生类中关联老师:多个学生对应一个老师-->
<!--<select id="getStudents" resultType="Student">-->
<!--select s.id,s.name,t.name* from mybatis.student as s,mybatis.teacher as t-->
<!--where s.tid = t.id-->
<!--</select>-->
<!--解决问题方式一:按查询结果嵌套处理,模拟数据库思想;-->
<select id="getStudents" resultMap="StudentTeacher">
select * from mybatis.student;
</select>
<!--关联上面的-->
<resultMap id="StudentTeacher" type="Student">
<id column="id" property="id"/>
<result column="name" property="name"/>
<!--属性和字段对应, 类和表对应, 对象和记录对应
关联一个字段
需求:拿到老师这个类的属性
association :关联,多对一
column:数据库对应的列名
property:对应属性名
javaType:多对一字段对应的java类型
select;关联一个语句
-->
<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 com.westos.dao;
import com.westos.pojo.Student;
import com.westos.utils.MyBatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.junit.Test;
import java.util.List;
public class test {
@Test
public void getStudents(){
SqlSessionFactory sqlSessionFactory = MyBatisUtils.getSqlSessionFactory();
SqlSession sqlSession = sqlSessionFactory.openSession();
StudentDao mapper = sqlSession.getMapper(StudentDao.class);
List<Student> students = mapper.getStudents();
for (Student student : students) {
System.out.println("学生姓名:"+student.getName()+"\t老师姓名:"+student.getTeacher().getName());
}
sqlSession.close();//关闭连接
}
}
4. 测试结果
多对一的处理方式二:
1. 编写接口
package com.westos.dao;
import com.westos.pojo.Student;
import java.util.List;
public interface StudentDao {
//获得全部学生的信息以及对应的老师
List<Student> getStudents();
//获得全部学生的信息以及对应的老师
List<Student> getStudentsTwo();
}
2. 编写处理的StudentMapper.xml
-
查询学生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="com.westos.dao.StudentDao">
<!--遇到问题:学生类中关联老师:多个学生对应一个老师-->
<!--<select id="getStudents" resultType="Student">-->
<!--select s.id,s.name,t.name* from mybatis.student as s,mybatis.teacher as t-->
<!--where s.tid = t.id-->
<!--</select>-->
<!--解决问题方式一:按查询结果嵌套处理,模拟数据库思想;-->
<select id="getStudents" resultMap="StudentTeacher">
select * from mybatis.student;
</select>
<!--关联上面的-->
<resultMap id="StudentTeacher" type="Student">
<id column="id" property="id"/>
<result column="name" property="name"/>
<!--属性和字段对应, 类和表对应, 对象和记录对应
关联一个字段
需求:拿到老师这个类的属性
association :关联,多对一
column:数据库对应的列名
property:对应属性名
javaType:多对一字段对应的java类型
select;关联一个语句
-->
<association column="tid" property="teacher" javaType="Teacher" select="getTeacher"/>
</resultMap>
<!--关联上面的文件-->
<select id="getTeacher" resultType="Teacher">
select * from mybatis.teacher where id = #{id}
</select>
<!--解决方式二:一个resultMap解决 :模拟面型对象思想-->
<select id="getStudentsTwo" resultMap="StudentTeacherTwo">
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="StudentTeacherTwo" type="Student">
<id property="id" column="id"/>
<result property="name" column="name"/>
<!--直接关联一个老师-->
<association property="teacher" javaType="Teacher">
<result property="name" column="tname"/>
</association>
</resultMap>
</mapper>
3. 测试类
package com.westos.dao;
import com.westos.pojo.Student;
import com.westos.utils.MyBatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.junit.Test;
import java.util.List;
public class test {
@Test
//解决方式一
public void getStudents(){
SqlSessionFactory sqlSessionFactory = MyBatisUtils.getSqlSessionFactory();
SqlSession sqlSession = sqlSessionFactory.openSession();
StudentDao mapper = sqlSession.getMapper(StudentDao.class);
List<Student> students = mapper.getStudents();
for (Student student : students) {
System.out.println("学生姓名:"+student.getName()+"\t老师姓名:"+student.getTeacher().getName());
}
sqlSession.close();//关闭连接
}
@Test
//解决方式二
public void getStudentsTwo(){
SqlSessionFactory sqlSessionFactory = MyBatisUtils.getSqlSessionFactory();
SqlSession sqlSession = sqlSessionFactory.openSession();
StudentDao mapper = sqlSession.getMapper(StudentDao.class);
List<Student> studentsTwo = mapper.getStudentsTwo();
for (Student student : studentsTwo) {
System.out.println("学生姓名:"+student.getName()+"\t老师姓名:"+student.getTeacher().getName());
}
sqlSession.close();//关闭连接
}
}
4. 测试结果
总结
- mybatis中遇到多对一的情况,要使用关联映射处理:使用association
- 两种处理思路:
- 数据库思想 : 联表查询
- OOP思想 :关联对象
10 . 一对多处理
一个老师对应多个学生
一对多的业务:使用collection处理
环境搭建
在idea中跟据数据表和测试所需要的环境(一对多)
一个老师对应多个学生
实体类
Student类
package com.westos.pojo;
public class Student {
private int id;
private String name;
//多个学生对一个老师
private Teacher teacher;
public Student() {
}
public Student(int id, String name, Teacher teacher) {
this.id = id;
this.name = name;
this.teacher = teacher;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Teacher getTeacher() {
return teacher;
}
public void setTeacher(Teacher teacher) {
this.teacher = teacher;
}
@Override
public String toString() {
return "Student{" +
"id=" + id +
", name='" + name + '\'' +
", teacher=" + teacher +
'}';
}
}
}
package com.westos.pojo;
import java.util.List;
public class Teacher {
private int id;
private String name;
//一个老师对应多个学生
private List<Student> students;
public Teacher() {
}
public Teacher(int id, String name, List<Student> students) {
this.id = id;
this.name = name;
this.students = students;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Student> getStudents() {
return students;
}
public void setStudents(List<Student> students) {
this.students = students;
}
@Override
public String toString() {
return "Teacher{" +
"id=" + id +
", name='" + name + '\'' +
", students=" + students +
'}';
}
}
编写dao接口
package com.westos.dao;
import com.westos.pojo.Teacher;
public interface TeacherDao {
//获得一个老师下的所有学生信息;老师是包含学生的集合
Teacher getTeacher(int id);
Teacher getTeacherTwo(int id);
}
对应mapper文件
<?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="com.westos.dao.TeacherDao">
<!--一对多的处理-->
<!--面向对象方式解决-->
<select id="getTeacher" resultMap="TeacherStudent">
select s.id as sid,s.name as sname,t.id as tid,t.name as tname
from mybatis.student as s,mybatis.teacher as t
where s.tid = t.id and t.id = #{id}
</select>
<resultMap id="TeacherStudent" type="Teacher">
<result property="name" column="tname"/>
<!--对多:collection-->
<collection property="students" ofType="Student">
<id property="id" column="sid"/>
<result property="name" column="sname"/>
</collection>
</resultMap>
<!--数据库思想-->
<!--数据库思想-->
<select id="getTeacherTwo" resultMap="TeacherStudent2">
select * from mybatis.teacher where id = #{id}
</select>
<resultMap id="TeacherStudent2" type="Teacher">
<collection property="students" javaType="ArrayList" ofType="Student" column="id" select="T2"/>
</resultMap>
<select id="T2" resultType="Student">
select * from mybatis.student where tid = #{id}
</select>
</mapper>
测试类
package com.westos.dao;
import com.westos.pojo.Teacher;
import com.westos.utils.MyBatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.junit.Test;
public class test {
@Test
public void getTeacher(){
SqlSessionFactory sqlSessionFactory = MyBatisUtils.getSqlSessionFactory();
SqlSession sqlSession = sqlSessionFactory.openSession();
TeacherDao mapper = sqlSession.getMapper(TeacherDao.class);
Teacher teacher = mapper.getTeacher(1);
System.out.println(teacher.getName());
System.out.println(teacher.getStudents());
}
@Test
public void getTeacherTwo(){
SqlSessionFactory sqlSessionFactory = MyBatisUtils.getSqlSessionFactory();
SqlSession sqlSession = sqlSessionFactory.openSession();
TeacherDao mapper = sqlSession.getMapper(TeacherDao.class);
Teacher teacher = mapper.getTeacherTwo(1);
System.out.println(teacher.getName());
System.out.println(teacher.getStudents());
}
}
测试结果:
- getTeacher
2. getTeacherTwo
总结
多对一:association 关联
一对多:collection 集合
两种解决方式:
- 面对对象的思想:关联对象
- SQL语句思想:联表查询