多对一和一对多

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

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. [HNOI2009]最小圈 题解

    题目大意 给你一个有向图,求出图中环的平均值的最小值 环的平均值定义:环中所有的边权和/环中点数量 思路 看到使平均值最大或最小,可以考虑分数规划 分数规划用于解决一些要让平均值最大或最小的问题 具体 ...

  2. 2020-07-24:聊一下zookeeper的同步算法。

    福哥答案2020-07-24: 同步算法基于 ZAB 协议,一种快速 Paxos 算法. 快速Paxos算法Paxos算法可能出现死循环,就是在两个Proposer总是在交替prepare.并且,Pa ...

  3. Memcached高可用组件之repcached

    在前边的tomcat session server msm的那篇博客我们用memcached做tomcat session服务器,默认官方memcached是不支持主从同步的,为了解决memcache ...

  4. eclipse中 sec/test/resource 文件夹消失怎么设置?

    右键改包--->build path --->Configure bulid path 按 add Folder 搞定.....

  5. 当Notification和Websocket遇到https、http

    @ 目录 一.http转为https请求 (1)生成证书1(crt证书转tomcat使用的jks) (2)配置证书1 (3)生成证书2 (4)配置证书2 二.Websocket改为https连接 后言 ...

  6. 【MySQL】记一次线上重大事故:二狗子竟然把线上数据库删了!!

    写在前面 估计二狗子这几天是大姨夫来了,心情很郁闷,情绪也很低落,工作的时候也有点心不在焉.让他发个版本,结果,一行命令下去把线上的数据库删了!你没听错:是删掉了线上的数据库!运营那边顿时炸了锅:怎么 ...

  7. 蓝牙RFCOMM通信

    最近需要在某个开发板上面通过蓝牙和手机蓝牙连接,并通过RFCOMM通信.还没有做过蓝牙RFCOMM相关工作,因此先在linux PC上面调试一下流程,并在此记录调试过程. 一.说明 RFCOMM协议基 ...

  8. Spring注解驱动开发04(给容器中注册组件的方式)

    给容器中注册组件的方式 1. 组件注解标注 + 包扫描(适用于自己写的类) //控制层组件 @Controller public class PersonController { } //业务逻辑层组 ...

  9. 4.oracle sql*plus常用命令

    一.sys用户和system用户Oracle安装会自动的生成sys用户和system用户(1).sys用户是超级用户,具有最高权限,具有sysdba角色,有create database的权限,该用户 ...

  10. MySQL经典练习题及答案,常用SQL语句练习50题

    表名和字段 –1.学生表 Student(s_id,s_name,s_birth,s_sex) –学生编号,学生姓名, 出生年月,学生性别 –2.课程表 Course(c_id,c_name,t_id ...