多对一和一对多

  • 多个学生,对应一个老师
  • 对于学生而言,关联: 多个学生,关联一个老师 [多对一]
  • 对于老师而言,集合: 一个老师,有很多学生 [一对多]

1. 复杂表的构建

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 INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('1', '小明', '1');
INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('2', '小红', '1');
INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('3', '小张', '1');
INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('4', '小李', '1');
INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('5', '小王', '1');

2. 测试环境搭建

1. 导入Lombok

<dependencies>
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
</dependency>
</dependencies>

2. 新建实体类

package com.wang.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor; @Data
@AllArgsConstructor
@NoArgsConstructor
public class Student {
private int id;
private String name; //学生需要关联一个老师(物理外键)
private Teacher teacher;
}
package com.wang.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor; @Data
@NoArgsConstructor
@AllArgsConstructor
public class Teacher {
private int id;
private String name;
}

3. 建立Mapper接口

package com.wang.dao;

import com.wang.pojo.Student;

import java.util.List;

public interface StudentMapper {

    //查询所有的学生信息,以及对应的老师的信息
List<Student> getStudentInfo();
}
package com.wang.dao;

import com.wang.pojo.Teacher;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select; public interface TeacherMapper { @Select("select * from teacher where id = #{tid}")
Teacher getTeacher(@Param("tid") int id); }

4. 建立Mapper.xml文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.wang.dao.StudentMapper"> </mapper>
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.wang.dao.TeacherMapper"> </mapper>

5. 在核心配置文件汇总绑定Mapper接口或者文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<!--configuration 核心配置文件-->
<configuration> <!--引入外部配置文件,由于此处都在resource目录下,直接写文件名-->
<properties resource="db.properties"/> <!--标准的日志工厂实现-->
<settings>
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings> <!--可以给实体类起别名-->
<typeAliases>
<typeAlias type="com.wang.pojo.Teacher" alias="Teacher"/>
</typeAliases> <environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${pwd}"/>
</dataSource>
</environment>
</environments> <mappers>
<mapper resource="com/wang/dao/StudentMapper.xml"/>
<!--由于使用了注解,Teacher要用class关联接口!-->
<mapper class="com.wang.dao.TeacherMapper"/>
</mappers> </configuration>

6. 测试查询是否成功

import com.wang.dao.TeacherMapper;
import com.wang.pojo.Teacher;
import com.wang.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test; public class MyTest { @Test
public void TestGetTeacher() {
SqlSession sqlSession = MybatisUtils.getSqlSession(); TeacherMapper mapper = sqlSession.getMapper(TeacherMapper.class);
Teacher teacher = mapper.getTeacher(1);
System.out.println(teacher); sqlSession.close();
}
}

3. 多对一处理

1. 按照查询嵌套处理(子查询)

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.wang.dao.StudentMapper"> <!--
思路:
1.查询所有的学生信息
2.根据查询出来的学生的tid,寻找对应的老师
-->
<select id="getStudentInfo" resultMap="StudentTeacher">
select * from student;
</select>
<resultMap id="StudentTeacher" type="Student">
<result property="id" column="id"/>
<result property="name" column="name"/>
<!--复杂的属性,我们需要单独处理
对象:association
集合:collection
-->
<association property="teacher" column="tid" javaType="Teacher" select="getTeacher"/>
</resultMap> <select id="getTeacher" resultType="Teacher">
select * from teacher where id = #{id};
</select> </mapper>

2. 按照结果嵌套处理(连表查询)

<!--===========================================================-->
<!--按照结果嵌套处理-->
<select id="getStudentInfo2" resultMap="StudentTeacher2">
select s.id as sid, s.name as sname, t.name as tname
from student as s, teacher as t
where s.tid = t.id;
</select> <resultMap id="StudentTeacher2" type="Student">
<result property="id" column="sid"/>
<result property="name" column="sname"/>
<association property="teacher" javaType="Teacher">
<result property="name" column="tname"/>
</association>
</resultMap>

4. 一对多处理

1. 环境搭建,修改实体类

package com.wang.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor; @Data
@AllArgsConstructor
@NoArgsConstructor
public class Student {
private int id;
private String name;
private int tid;
}
package com.wang.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor; import java.util.List; @Data
@NoArgsConstructor
@AllArgsConstructor
public class Teacher {
private int id;
private String name; //一个老师拥有多个学生
private List<Student> students;
}

2. 按照结果嵌套处理

<!--按结果嵌套查询-->
<select id="getTeacherById" resultMap="TeacherStudent">
select s.id as sid, s.name as sname, t.name as tname, t.id as tid
from student as s
inner join teacher as t
on s.tid = t.id and tid = #{tid};
</select>
<!--复杂的属性,我们需要单独处理
对象: association 集合: collection
JavaType="" 指定属性的类型!
对于集合中的泛型信息,我们使用ofType获取!
-->
<resultMap id="TeacherStudent" type="Teacher">
<result property="id" column="tid"/>
<result property="name" column="tname"/>
<collection property="students" ofType="Student">
<result property="id" column="sid"/>
<result property="name" column="sname"/>
<result property="tid" column="tid"/>
</collection>
</resultMap>

3. 按照查询嵌套处理

<select id="getTeacherById2" resultMap="TeacherStudent2">
select *
from teacher
where id = #{tid};
</select>
<resultMap id="TeacherStudent2" type="Teacher">
<collection property="students" javaType="ArrayLi st" ofType="Student" select="getStudentByTeacherId" column="id"/>
</resultMap> <select id="getStudentByTeacherId" resultType="Student">
select *
from student
where tid = #{tid}
</select>

此种方式,用于查询的字段必须显示指定才能正确显示!

两种显式指定的方式:

  1. 在SQL语句中指定
  2. 在结果集映射中使用result标签通过property和column指定

5. 小结

  1. association 关联 多对一
  2. collection 集合 一对多
  3. javaType & ofType
    1. javaType 用来指定实体类中属性的类型
    2. ofType 用来指定映射到List或者集合中的pojo类型,泛型中的约束类型

6. 注意点

  • 保证SQL的可读性,尽量保证通俗易懂
  • 注意一对多和多对一中,属性名和字段的问题!
  • 如果问题不好排查错误,可以使用日志,建议使用Log4j

Mybatis-多对一和一对多的更多相关文章

  1. mybatis多对一与一对多

    步骤: 1.创建maven项目 2.编写工具类 3.编写实体类 4.编写mapper接口 5.配置xml 6.测试 多对一:多个学生关联一个老师 工具类: //sqlSessionFactory -- ...

  2. Mybatis 多对一和一对多 学习总结04

    1.Mybatis 组件的声明周期 ​ 声明周期是组件的重要问题,Mybatis也常用语多线程环境,错误使用会造成多线程并发问题,为正确编写Mybatis应用程序,我们要掌握Mybatis组件的声明周 ...

  3. MyBatis多对一,一对多,多对多,一对多关联查询

    一.Person实体类 1 public class Person { 2 private Integer personId; 3 private String name; 4 private Int ...

  4. java web(六):mybatis之一对一、一对多、多对多映射

    前言: 百度百科: MyBatis 是一款优秀的持久层框架,它支持定制化 SQL.存储过程以及高级映射.MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集.MyBatis 可 ...

  5. 后端框架的学习----mybatis框架(9、多对一处理和一对多处理)

    9.多对一处理和一对多处理 #多对一 <!--按照结果集嵌套查询--> <select id="getAllStudent1" resultMap="S ...

  6. Java基础-SSM之mybatis多对多关联

    Java基础-SSM之mybatis多对多关联 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.准备测试环境(创建数据库表) 1>.创建teas,stus,links表 u ...

  7. mybatis多对一关联

    mybatis多对一关联查询实现 1.定义实体 定义实体的时候需要注意,若是双向关联,就是说双方的属性中都含有对方对象作为域属性出现, 那么在写toString()方法时需要注意,只让某一方输出即可, ...

  8. Hibernate关联映射(单项多对一和一对多、双向一对多)

    最近总是接触着新的知识点来扩展自己的知识面:不停的让自己在原地接触天空的感觉真的很美好!!!革命没有成功,程序员的我们怎么能不努力呢...... 一.用员工和部门来剖析关联映射的原理. 1)从这张截图 ...

  9. 一步步学习NHibernate(5)——多对一,一对多,懒加载(2)

    请注明转载地址:http://www.cnblogs.com/arhat 通过上一章的学习,我们建立了Student和Clazz之间的关联属性,并从Student(many)的一方查看了Clazz的信 ...

  10. MyBatis多对多查询

    -------------------siwuxie095                                 MyBatis 多对多查询         以订单和商品为例,即 一个订单可 ...

随机推荐

  1. java循环语句for与无限循环

    一 for循环 for循环语句是最常用的循环语句,一般用在循环次数已知的情况下. 格式: for(初始化表达式; 循环条件; 操作表达式){ 执行语句 ……… } 循环流程: for(① ; ② ; ...

  2. C#LeetCode刷题之#892-三维形体的表面积(Surface Area of 3D Shapes)

    问题 该文章的最新版本已迁移至个人博客[比特飞],单击链接 https://www.byteflying.com/archives/4136 访问. 在 N * N 的网格上,我们放置一些 1 * 1 ...

  3. C#LeetCode刷题-深度优先搜索

    深度优先搜索篇 # 题名 刷题 通过率 难度 98 验证二叉搜索树   22.2% 中等 99 恢复二叉搜索树   45.1% 困难 100 相同的树   48.1% 简单 101 对称二叉树   4 ...

  4. Vue 使用mixin抽取共通方法

    引入原因: 当一段逻辑在不同的地方使用时 step-1: 定义mixin文件,methods里有一个handleToLink方法 /** * this mixin file will be used ...

  5. VUE——添加组件模块(图表)

    Vue是由一个个小模块组成的,模块可以让页面简介还可以复用: 1.不固定数据数量传到子组件 父组件: <chartVue v-for="(item, index) in chartLi ...

  6. 复习 Array,重学 JavaScript

    1 数组与对象 在 JavaScript 中,一个对象的键只能有两种类型:string 和 symbol.下文只考虑键为字符串的情况. 1.1 创建对象 在创建对象时,若对象的键为数字,或者由 字母+ ...

  7. 如何在 asp.net core 的中间件中返回具体的页面

    前言 在 asp.net core 中,存在着中间件这一概念,在中间件中,我们可以比过滤器更早的介入到 http 请求管道,从而实现对每一次的 http 请求.响应做切面处理,从而实现一些特殊的功能 ...

  8. AS报错:gradle project sync failed

    情形一: Android studio下突然报错: gradle project sync failed.Basic functionality(e.g.editing,debugging) will ...

  9. 最新通达OA-getshell 漏洞复现

    0x00 通达简介 通达OA国内常用的办公系统,使用群体,大小公司都可以,其此次安全更新修复的高危漏洞为任意用户登录漏洞.攻击者在远程且未经授权的情况下,通过利用此漏洞,可以直接以任意用户身份登录到系 ...

  10. java 二分查找的注意事项

    二分查找也是最简单的算法之一了.但是最近发现一般的写法会有问题. public int search(int[] nums, int target) { int left = 0; int right ...