MyBatis(十六):多对一的处理

打印 上一主题 下一主题

主题 986|帖子 986|积分 2958

现在我们就开始更加深入的学习了,今天我们要学习的是多对一的处理。
在正式开始之前我们需要做一些准备工作。
一、在数据库建立两张新的表并插入数据
  1. CREATE TABLE `teacher` (
  2.   `id` INT(10) NOT NULL,
  3.   `name` VARCHAR(30) DEFAULT NULL,
  4.   PRIMARY KEY(`id`)
  5. ) ENGINE=INNODB DEFAULT CHARSET=utf8
  6. INSERT INTO `teacher`(`id`, `name`) VALUES (1, '刘老师');
  7. CREATE TABLE `student` (
  8.   `id` INT(10) NOT NULL,
  9.   `name` VARCHAR(30) DEFAULT NULL,
  10.   `tid` INT(10) DEFAULT NULL,
  11.   PRIMARY KEY (`id`),
  12.   KEY `fktid` (`tid`),
  13.   CONSTRAINT `fktid` FOREIGN KEY (`tid`) REFERENCES `teacher` (`id`)
  14. )ENGINE=INNODB DEFAULT CHARSET=utf8
  15. INSERT INTO `student` (`id`,`name`,`tid`) VALUES (1,'小赵','1');
  16. INSERT INTO `student` (`id`,`name`,`tid`) VALUES (2,'小钱','1');
  17. INSERT INTO `student` (`id`,`name`,`tid`) VALUES (3,'小孙','1');
  18. INSERT INTO `student` (`id`,`name`,`tid`) VALUES (4,'小李','1');
  19. INSERT INTO `student` (`id`,`name`,`tid`) VALUES (5,'小周','1');
复制代码
上述SQL语句建立了一个teacher表,一个student表,student表的tid与teacher表的id相关联。
二、建立一个新的项目
我们建立一个全新的子项目
1.建立MyBatis的核心配置文件mybatis-config.xml
  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <!DOCTYPE configuration
  3.         PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  4.         "http://mybatis.org/dtd/mybatis-3-config.dtd">
  5. <configuration>
  6.     <properties resource="db.properties" />
  7.     <settings>
  8.         <setting name="logImpl" value="STDOUT_LOGGING"/>
  9.     </settings>
  10.    
  11.     <typeAliases>
  12.         <package name="com.jms.pojo"/>
  13.     </typeAliases>
  14.     <environments default="development">
  15.         <environment id="development">
  16.             <transactionManager type="JDBC"/>
  17.             <dataSource type="POOLED">
  18.                 <property name="driver" value="${driver}"/>
  19.                 <property name="url" value="${url}"/>
  20.                 <property name="username" value="${username}"/>
  21.                 <property name="password" value="${password}"/>
  22.             </dataSource>
  23.         </environment>
  24.     </environments>
  25. </configuration>
复制代码
2.建立db.properties
  1. driver=com.mysql.jdbc.Driver
  2. url=jdbc:mysql://localhost:3306/MyBaties?useSSL=true&useUnicode=true&characterEncoding=UTF-8
  3. username=root
  4. password=123456
复制代码
3.建立MyBatisUtil工具类
  1. package com.jms.utils;
  2. import org.apache.ibatis.io.Resources;
  3. import org.apache.ibatis.session.SqlSession;
  4. import org.apache.ibatis.session.SqlSessionFactory;
  5. import org.apache.ibatis.session.SqlSessionFactoryBuilder;
  6. import java.io.IOException;
  7. import java.io.InputStream;
  8. //SqlSessionFactory-->SqlSession
  9. public class MyBatisUtil {
  10.     private static SqlSessionFactory sqlSessionFactory;
  11.     //获取SqlSessionFactory对象
  12.     static {
  13.         try {
  14.             String resource = "mybatis-config.xml";
  15.             InputStream inputStream = Resources.getResourceAsStream(resource);
  16.             sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
  17.         } catch (IOException e) {
  18.             e.printStackTrace();
  19.         }
  20.     }
  21.     //通过SqlSessionFactory获取SqlSession对象,其中包含了面向数据库执行执行SQL命令所需要的方法
  22.     public static SqlSession getSqlSession() {
  23.         return sqlSessionFactory.openSession(true);
  24.     }
  25. }
复制代码
4.建立实体类
Student
  1. package com.jms.pojo;
  2. public class Student {
  3.     private int id;
  4.     private String name;
  5.     private Teacher teacher;
  6.     public Student() {
  7.     }
  8.     public Student(int id, String name, Teacher teacher) {
  9.         this.id = id;
  10.         this.name = name;
  11.         this.teacher = teacher;
  12.     }
  13.     public int getId() {
  14.         return id;
  15.     }
  16.     public void setId(int id) {
  17.         this.id = id;
  18.     }
  19.     public String getName() {
  20.         return name;
  21.     }
  22.     public void setName(String name) {
  23.         this.name = name;
  24.     }
  25.     public Teacher getTeacher() {
  26.         return teacher;
  27.     }
  28.     public void setTeacher(Teacher teacher) {
  29.         this.teacher = teacher;
  30.     }
  31.     @Override
  32.     public String toString() {
  33.         return "Student{" +
  34.                 "id=" + id +
  35.                 ", name='" + name + '\'' +
  36.                 ", teacher=" + teacher +
  37.                 '}';
  38.     }
  39. }
复制代码
Teacher
  1. package com.jms.pojo;
  2. public class Teacher {
  3.     private int id;
  4.     private String name;
  5.     public Teacher(int id, String name) {
  6.         this.id = id;
  7.         this.name = name;
  8.     }
  9.     public Teacher() {
  10.     }
  11.     public int getId() {
  12.         return id;
  13.     }
  14.     public void setId(int id) {
  15.         this.id = id;
  16.     }
  17.     public String getName() {
  18.         return name;
  19.     }
  20.     public void setName(String name) {
  21.         this.name = name;
  22.     }
  23.     @Override
  24.     public String toString() {
  25.         return "Teacher{" +
  26.                 "id=" + id +
  27.                 ", name='" + name + '\'' +
  28.                 '}';
  29.     }
  30. }
复制代码
5.建立Mapper接口
StudentMapper
TeacherMapper
6.建立Mapper.xml配置文件
StudentMapper.xml
  1. [/code]TeacherMapper.xml
  2. [code]
复制代码
6.在核心配置文件mybatis-config.xml中建立映射
  1.     <mappers>
  2.         <mapper resource="com/jms/dao/TeacherMapper.xml"/>
  3.         <mapper resource="com/jms/dao/StudentMapper.xml"/>
  4.     </mappers>
复制代码
 7.测试
(1)在接口中写一个方法
  1. package com.jms.dao;
  2. import com.jms.pojo.Teacher;
  3. import org.apache.ibatis.annotations.Select;
  4. import java.util.List;
  5. public interface TeacherMapper {
  6.     List<Teacher> getTeacherList();
  7. }
复制代码
(2)在Mapper.xml文件中实现
  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <!DOCTYPE mapper
  3.         PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  4.         "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  5. <mapper namespace="com.jms.dao.TeacherMapper">
  6.     <select id="getTeacherList" resultType="teacher">
  7.         select * from mybaties.teacher
  8.     </select>
  9. </mapper>
复制代码
(3)junit测试
  1. import com.jms.dao.TeacherMapper;
  2. import com.jms.pojo.Teacher;
  3. import com.jms.utils.MyBatisUtil;
  4. import org.apache.ibatis.session.SqlSession;
  5. import org.junit.Test;
  6. import java.util.List;
  7. public class MapperTest {
  8.     @Test
  9.     public void test() {
  10.         SqlSession sqlSession = MyBatisUtil.getSqlSession();
  11.         TeacherMapper teacherMapper = sqlSession.getMapper(TeacherMapper.class);
  12.         List<Teacher> teacherList = teacherMapper.getTeacherList();
  13.         for (Teacher teacher : teacherList) {
  14.             System.out.println(teacher);
  15.         }
  16.     }
  17. }
复制代码

 
 
测试结果没有问题。
至此,我们的数据库和项目都搭建完成。
接下来就进行多对一处理的实现。
三、多对一处理的实现
首先我们要清楚我们要做什么?
我们要查询所有的student信息。查询所有student信息不是很简单吗?一般来说确实很简答,但是我们Student类中有一个属性是Teacher对象。Teacher对象还有着自己的id和name。所以我们要查的是student表中的id和name,以及它们的tid所对应的teacher表中的id和name。
我们先利用SQL来查询看看。
  1. select s.id,s.name,t.id,t.name
  2. from student as s,teacher as t
  3. where s.tid = t.id
复制代码

上表即我们想要得到的结构。
那么在MyBatis中我们如何去实现呢?
我们有两种方法。
1.按照结果嵌套处理
顾名思义,就是先通过查询得到结果,把结果中的四个列对应给Student类的三个属性,最后两列对应给Teacher对象的两个属性。
由于student表和teacher中的id字段和name字段名字相同,所以我们在MyBatis中查询的时候应该给它起别名(不同的话就没有必要了)。
(1)在StudentMapper接口中声明方法
  1. package com.jms.dao;
  2. import com.jms.pojo.Student;
  3. import java.util.List;
  4. public interface StudentMapper {
  5.     List<Student> getStudentList();
  6. }
复制代码
(2)在StudentMapper.xml中实现接口中的方法
  1.     <mappers>
  2.         <mapper resource="com/jms/dao/TeacherMapper.xml"/>
  3.         <mapper resource="com/jms/dao/StudentMapper.xml"/>
  4.     </mappers>    <mappers>
  5.         <mapper resource="com/jms/dao/TeacherMapper.xml"/>
  6.         <mapper resource="com/jms/dao/StudentMapper.xml"/>
  7.     </mappers>    <mappers>
  8.         <mapper resource="com/jms/dao/TeacherMapper.xml"/>
  9.         <mapper resource="com/jms/dao/StudentMapper.xml"/>
  10.     </mappers>                select s.id as sid,s.name as sname,t.id as tid,t.name as tname        from mybaties.student as s,mybaties.teacher as t        where s.tid = t.id   
复制代码
我们看上面的配置,还是常规的select语句和结果映射,唯一有变化的就是结果映射中多了一个对于复杂属性的处理。
官方文档中是这样说明的:
association – 一个复杂类型的关联;许多结果将包装成这种类型
  嵌套结果映射 – 关联可以是 resultMap 元素,或是对其它结果映射的引用
javaType 一个 Java 类的全限定名,或一个类型别名(关于内置的类型别名,可以参考上面的表格)。 如果你映射到一个 JavaBean,MyBatis 通常可以推断类型。然而,如果你映射到的是 HashMap,那么你应该明确地指定 javaType 来保证行为与期望的相一致。
(3)junit测试
  1. import com.jms.dao.StudentMapper;
  2. import com.jms.dao.TeacherMapper;
  3. import com.jms.pojo.Student;
  4. import com.jms.pojo.Teacher;
  5. import com.jms.utils.MyBatisUtil;
  6. import org.apache.ibatis.session.SqlSession;
  7. import org.junit.Test;
  8. import java.util.List;
  9. public class MapperTest {
  10.     @Test
  11.     public void getStudents() {
  12.         SqlSession sqlSession = MyBatisUtil.getSqlSession();
  13.         StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);
  14.         List<Student> studentList = studentMapper.getStudentList();
  15.         for (Student student : studentList) {
  16.             System.out.println(student);
  17.         }
  18.     }
  19. }
复制代码
测试结果如下:

 成功得到了想要的结果。
2.按照查询进行嵌套处理
顾名思义,就是查询中嵌套着查询。这个我们要实现,很明显我们需要先对student表进行查询,将结果中的tid作为第二个查询的条件来查询teacher表。
(1)在StudentMapper接口声明方法
  1. List<Student> getStudentList2();
复制代码
(2)在StudentMapper.xml中实现接口中的方法
  1.       <mappers>
  2.         <mapper resource="com/jms/dao/TeacherMapper.xml"/>
  3.         <mapper resource="com/jms/dao/StudentMapper.xml"/>
  4.     </mappers>                select * from mybaties.student                select * from mybaties.teacher where id=#{tid}   
复制代码
这种方法相比第一种可能难理解一些,但也不是很难。将tid列与teacher属性进行对应,然后嵌套一个查询,这个查询返回的是一个Teacher类型,刚好把查询结果返给对应的teacher属性。
这里令我感到意外的是select的id,竟然还能作为被引用的对象,于是我看了一下官方文档的内容:
Select 元素的属性属性描述id在命名空间中唯一的标识符,可以被用来引用这条语句。
select的id在命名空间的标识符就是说去接口中找方法名,同样说到可以被引用,嗯,学习了。
(3)junit测试

 
 同样得到了结果。
 
(本文仅作个人学习记录用,如有纰漏敬请指正)
 

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

勿忘初心做自己

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表