多对一和一对多

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

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. BN系列-未完待续

    BN.LN.IN.GN Cross-Iteration Batch Normalization 因为有时候我们的计算能力有限,所以BN设置的比较小,这样BN效果就比较差. 因此我们将最近几次的batc ...

  2. LInux回顾与Shell编程

    一.Linux回顾 因为要学习Hadoop大数据,会用到Linux服务器集群来做,因此有必要回顾一下当年大一所学习的Linux知识 ①Linux系统有7个运行级别(runlevel): 运行级别0:系 ...

  3. 用Java制作斗地主

    首先,按照斗地主规则,完成洗牌发牌的动作.如图: 具体规则: 1. 组装54张扑克牌 2. 将54张牌顺序打乱 3. 三个玩家参与游戏,三人交替摸牌,每人17张牌,最后三张留作底牌. 4. 查看三人各 ...

  4. ThinkPHP 6.0 基础教程 - 安装

    ThinkPHP6.0 的环境: PHP >= 7.1.0 我本地环境: Win10 PhpStudy 安装 PhpStudy 如果你已经安装 PhpStudy 或其他环境,请忽略这里 安装方法 ...

  5. vue调起微信JSDK 扫一扫,相册等需要注意的事项

    在VUE里面需要注意的第一个问题就是路由得设置成 2:第二个就是 跳转路由的时候 不要用this.$router.push 或者this.$router.replace  前者在ios 和安卓端都调不 ...

  6. 修改vsftpd的默认根目录/var/ftp/pub到另一个目录

    修改ftp的根目录只要修改/etc/vsftpd/vsftpd.conf文件即可: 加入如下几行: local_root=/var/www/html chroot_local_user=YES ano ...

  7. 面试28k职位,老乡面试官从HashCode到HashMap给我讲了一下午!「回家赶忙整理出1.6万字的面试材料」

    作者:小傅哥 博客:https://bugstack.cn 目录 一.前言 二.HashCode为什么使用31作为乘数 1. 固定乘积31在这用到了 2. 来自stackoverflow的回答 3. ...

  8. mr原理简单分析

    背景 又是一个周末一天一天的过的好快,今天的任务干啥呢,索引总结一些mr吧,因为前两天有面试问过我?我当时也是简单说了一下,毕竟现在写mr程序的应该很少很少了,废话不说了,结合官网和自己理解写起. 官 ...

  9. JS 对象基本用法

    声明对象的两种语法 let obj = { 'name': 'frank', 'age': 18 } let obj = new Object({'name': 'frank'}) 如何删除对象的属性 ...

  10. Kubernetes使用Eedpoints连接外部服务端口

    Kubernetes使用Eedpoints连接外部服务端口 背景: 在Kubernetes的使用环境中,我们经常要连接外部的一些服务,比如mysql Elasticsearch kafka 等等外部的 ...