Mybatis对于多对多关系下的查询提供了集合(collection)的概念来解决,collection属性是resultMap高级结果映射的子集,首先,在本例中我们使用的是集合元素来解决多对多的查询。 然后你会注意到有一个新的 “ofType” 属性。这个属性非常重要,它用来将 JavaBean(或字段)属性的类型和集合存储的类型区分开来。在集合中ofType指的是集合中元素的类型。

  首先介绍一下Demo情况:

  • 实体类:User(用户)类和Role(角色)类,类中的属性在后面代码中贴出
  • 关系:一个用户可以有多个角色,一个角色可以赋予多个用户中
  • 数据库表结构:用户表、角色表、中间表(用于存储用户和角色的关系)
  • 本例中实现查询的目标:查询用户时同时获取用户所拥有的角色的信息(当查询角色时同时获取角色所属用户的信息的情况和下面的例子原理一样,主要是修改select中的sql语句)

  1.用户实体类以及角色实体类

public class User implements Serializable{
private Integer id;
private String username;
private Date birthday;
private String sex;
private String address;
private List<Role> roles; get和set方法省略 ......
}
public class Role implements Serializable{
private Integer roleId;
private String roleName;
private String roleDesc;
private List<User> users;
get和set方法省略 ......
}

  这里主要是增加用户所拥有的角色的List属性和角色所属用户的List属性,后面做resultMap结果映射的时候使用。

  2.数据库表结构

DROP TABLE IF EXISTS user;
CREATE TABLE user (
id INT(11) NOT NULL auto_increment,
username VARCHAR(32) NOT NULL COMMENT '用户名称',
birthday datetime default NULL COMMENT '生日',
sex char(1) default NULL COMMENT '性别',
address varchar(256) default NULL COMMENT '地址',
PRIMARY KEY (id)
)ENGINE=InnoDB default CHARSET=utf8
INSERT INTO `user` VALUES ('41', '老王', '2018-02-27 17:47:08', '男', '石家庄');
INSERT INTO `user` VALUES ('45', '老李', '2018-02-27 17:47:08', '男', '石家庄');
INSERT INTO `user` VALUES ('46', '老郭', '2018-02-27 17:47:08', '男', '石家庄');
INSERT INTO `user` VALUES ('47', 'mde', '2019-06-26 15:04:25', '女', '河南');
INSERT INTO `user` VALUES ('48', 'nan', '2019-08-01 15:04:54', '女', '合肥'); DROP TABLE IF EXISTS role;
CREATE TABLE role(
ID int(11) NOT NULL COMMENT '编号',
ROLE_NAME VARCHAR(30) DEFAULT NULL COMMENT '角色名称',
ROLE_DESC VARCHAR(60) DEFAULT NULL COMMENT '角色描述',
PRIMARY KEY (ID)
)ENGINE=INNODB DEFAULT CHARSET=utf8 INSERT INTO role (ID,ROLE_NAME,ROLE_DESC) VALUES (1,'院长','管理整个学院'),(2,'总裁','管理整个公司'),(3,'校长','管理整个学校'); DROP TABLE IF EXISTS user_role;
CREATE TABLE user_role(
UID int(11) NOT NULL COMMENT '用户编号',
RID INT(11) NOT NULL COMMENT '角色编号',
PRIMARY KEY (UID,RID),
CONSTRAINT FK_Reference_10 FOREIGN KEY(RID) REFERENCES role(ID),
CONSTRAINT FK_Reference_9 FOREIGN KEY(UID) REFERENCES user(id)
)ENGINE=INNODB DEFAULT CHARSET=utf8;
INSERT INTO user_role(UID,RID) VALUES(41,1),(45,1),(41,2);

这里主要是增加了中间表。

  3.在UserDao接口中声明查询所有用户的方法findAll();

    /**
* 查询所有的用户同时查询出所拥有的角色的信息
*
* @return
*/
List<User> findAll();

  4.在UserDao.xml中配置findAll()方法

<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.dao.UserDao">
<resultMap id="userMap" type="com.example.domain.User">
<id property="id" column="id"/>
<result property="username" column="username"/>
<result property="birthday" column="birthday"/>
<result property="sex" column="sex"/>
<result property="address" column="address"/>
<collection property="roles" ofType="com.example.domain.Role" resultMap="roleMap"/>
</resultMap>
<resultMap id="roleMap" type="com.example.domain.Role">
<id property="roleId" column="rid"/>
<result property="roleName" column="ROLE_NAME"/>
<result property="roleDesc" column="ROLE_DESC"/>
</resultMap>
<select id="findAll" resultMap="userMap">
SELECT u.*,r.ID as rid,r.ROLE_DESC,r.ROLE_NAME FROM user u
LEFT OUTER JOIN user_role ur on u.id = ur.UID
LEFT OUTER JOIN role r on ur.RID = r.ID
</select>
</mapper>

  实现多对多关系查询的主要工作都放在了这里,首先通过resultMap 声明用户类的结果映射,id以及result等标签就是User类中的基本属性,User类中的角色属性roles通过collection集合标签来映射到结果集中,<collection property="roles" ofType="com.example.domain.Role" resultMap="roleMap"/>,property对应User类中声明的roles属性,ofType用于标识集合中元素的类型,resultMap用于引用其他的结果映射来说明集合中元素的属性,在这里为roleMap。如果roleMap不在其他地方使用,也可以直接将角色的属性直接配置在collection属性的子集里,如以下形式也可以使用。

    <resultMap id="userMap" type="com.example.domain.User">
<id property="id" column="id"/>
<result property="username" column="username"/>
<result property="birthday" column="birthday"/>
<result property="sex" column="sex"/>
<result property="address" column="address"/>
<!--<collection property="roles" ofType="com.example.domain.Role" resultMap="roleMap"/>-->
<collection property="roles" ofType="com.example.domain.Role">
        <!--这里的rid是role表中的id,在select语句中为了防止id字段在两个表中都出现导致的重复,所以给role的字段id 起了别名 注意要与select中的别名保持一致-->
<id property="roleId" column="rid"/>
<result property="roleName" column="ROLE_NAME"/>
<result property="roleDesc" column="ROLE_DESC"/>
</collection>
</resultMap>

select中的SQL查询语句解释:

 <select id="findAll" resultMap="userMap">
SELECT u.*,r.ID as rid,r.ROLE_DESC,r.ROLE_NAME FROM user u
LEFT OUTER JOIN user_role ur on u.id = ur.UID
LEFT OUTER JOIN role r on ur.RID = r.ID
</select>

  u.*:查询USER表中所有的属性

  r.ID as rid:对于role表中的id起一个别名rid

  user u LEFT OUTER JOIN user_role ur on u.id = ur.UID:前面的表左连接后面的表,并且连接条件是User表中的id与User_role表中的uid相等

  5.测试代码

 public class UserDaoTest {
private InputStream in;
private SqlSession session; private UserDao userDao;
private SqlSessionFactory factory;
@Before
public void init()throws Exception{
//获取配置文件
in = Resources.getResourceAsStream("SqlMapConfig.xml");
//获取工厂
factory = new SqlSessionFactoryBuilder().build(in); session = factory.openSession(); userDao = session.getMapper(UserDao.class);
}
@After
public void destory()throws Exception{
session.commit();
session.close();
in.close();
}
@Test
public void findAllTest(){
List<User> userList = userDao.findAll();
for (User user: userList){
System.out.println("每个用户的信息");
System.out.println(user);
System.out.println(user.getRoles());
}
}

6.测试结果

mybatis多表查询之多对多关系查询的实现-xml方式的更多相关文章

  1. mybatis实战教程二:多对一关联查询(一对多)

    多对一关联查询 一.数据库关系.article表和user表示多对一的关系 CREATE TABLE `article` ( `id` ) NOT NULL AUTO_INCREMENT, `user ...

  2. Hibernate 、多表关联映射 - 多对多关系映射(many-to-many)

    hibernate.cfg.xml: <hibernate-configuration> <session-factory name="sessionFactory&quo ...

  3. 数据表设计:多对多关系E-R图转换——中间表

    链接:https://blog.csdn.net/vainfanfan/article/details/80568784 链接2:https://www.cnblogs.com/hiwangzi/p/ ...

  4. Hibernate 、多表关联映射-多对一关系(many-to-one)

    Hibernate.cfg.xml: <session-factory name="sessionFactory"> <property name="h ...

  5. mybatis的动态sql编写以及一对一关系查询和一对多的查询

    创建mybatis数据库,运行以下sql语句 /* SQLyog Ultimate v8.32 MySQL - 5.5.27 : Database - mybatis **************** ...

  6. Django-多对多关系的三种创建方式-forms组件使用-cookie与session-08

    目录 表模型类多对多关系的三种创建方式 django forms 组件 登录功能手写推理过程 整段代码可以放过来 forms 组件使用 forms 后端定义规则并校验结果 forms 前端渲染标签组件 ...

  7. [NHibernate]多对多关系(关联查询)

    目录 写在前面 文档与系列文章 多对多关系关联查询 总结 写在前面 上篇文章介绍了nhibernate中对一对多关系进行关联查询的几种方式,以及在使用过程需要注意的问题.这篇文章对多对多关系的查询处理 ...

  8. [转]NHibernate之旅(11):探索多对多关系及其关联查询

    本节内容 多对多关系引入 多对多映射关系 多对多关联查询 1.原生SQL关联查询 2.HQL关联查询 3.Criteria API关联查询 结语 多对多关系引入 让我们再次回顾在第二篇中建立的数据模型 ...

  9. MySQL基础9-主键约束、外键约束、等值连接查询、一对一和多对多关系

    1.主键约束和外键约束 外键约束 * 外键必须是另一表的主键的值(外键要引用主键!) * 外键可以重复 * 外键可以为空 * 一张表中可以有多个外键! 概念模型在数据库中成为表 数据库表中的多对一关系 ...

随机推荐

  1. Excel催化剂图表系列之一键完成IBCS国际商业标准图表

    在数据分析领域,最后一公里的图表输出,是一片十分广阔的领域.一直以来,笔者深知不是这一方面的能手,学习上也仅仅是浅尝而止.没有往其深入研究并有所产出.很幸运地在数据圈子能够结识到其他的志同道合的伙伴, ...

  2. python购物车升级版

    各文件内容 前言 功能架构等请参考前一篇博客,此篇博客为进阶版的存代码展示. 详细文件内容 启动文件 starts.py启动文件 import os import sys BASE_DIR = os. ...

  3. Python_Day1_人人都爱列表

    列表由一系列按特定顺序排列的元素组成.你可以创建包含字母表中所有字母.数字0~9或 所有家庭成员姓名的列表;也可以将任何东西加入列表中,其中的元素之间可以没有任何关系. 鉴于列表通常包含多个元素,给列 ...

  4. java练习---4

    //程序员:罗元昊 2017.9.17 今天好累吖咦吖咦吖 package demo;import java.util.Scanner;public class Lk { public static ...

  5. 努力做一个优秀的programmer [ C# 影院售票系统]

    Cinema.cs类 [Serializable] // 电影院类 public class Cinema { public Cinema() { //二进制 SoldTickets = new Li ...

  6. vim中 E212:无法打开并写入文件的解决办法

    很简单,就是用管理员身份打开这个文件 不要被网上的一些乱七八糟的迷惑了 sudo vim ....... 解决了问题请点个赞,谢谢

  7. MyBatis在Spring环境下的事务管理

    MyBatis的设计思想很简单,可以看做是对JDBC的一次封装,并提供强大的动态SQL映射功能.但是由于它本身也有一些缓存.事务管理等功能,所以实际使用中还是会碰到一些问题--另外,最近接触了JFin ...

  8. Java 求字符串中出现频率最高字符

    前段时间接触的这个题目,大体理解了,还有些小地方仍待进一步品味,暂且记下. import java.util.ArrayList; import java.util.Arrays; import ja ...

  9. Docker Toolbox安装

    公司最近搭建docker环境,其中会遇到一些问题,在这里记录一下. 先来了解一下docker 一.基本概念 1.Docker中基本概念镜像(Image) 提到镜像,有对操作系统有一定认知的都知道,镜像 ...

  10. 2019牛客多校训练第三场H.Magic Line(思维)

    题目传送门 大致题意: 输入测试用例个数T,输入点的个数n(n为偶数),再分别输入n个不同的点的坐标,要求输出四个整数x1,y1,x2,y2,表示有一条经过点(x1,y1),(x2,y2)的直线将该二 ...