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. Ubuntu中目录右下角的锁标志

    在ubuntu中如果是用root权限创建的目录,在普通权限下展示时则会出现一个锁的标志,表明该目录是一个受保护的目录(只读,不能写入和删除),普通权限无法对其进行操作.如用命令sudo mkdir d ...

  2. Mybatis generator生成工具简单介绍

    Mybatis generator  其主要的功能就是方便,快捷的创建好Dao,entry,xml 加快了开发速度,使用方面根据其提供的规则配置好就OK 这里还有一个重要的开发场景,开发过程中,对数据 ...

  3. phpcms V9 常用的调用标签

    本文介绍phpcms v9中模板标签使用说明. >>调用根目录下phpcms\template\content\header文件 {template "content" ...

  4. leetcode 48 矩阵旋转可以这么简单

    一行代码解决矩阵旋转(方法三). 方法1: 坐标法 def rotate(self, matrix): n = len(matrix) # 求出矩阵长度 m = (n + 1) // 2 # 求出层数 ...

  5. windos10专业版激活(可用)

    电脑提示Windows许可证即将到期,于是自己就在网上找了一些教程,但是并没有激活成功,反而由即将到期变为了通知状态,尝试了各种密钥都不行,也下载了激活工具如暴风激活工具,KMS都不管用,尝试了好多方 ...

  6. Redis项目实战---应用及理论(三)---Jedis使用

    Jedis即redis java客户端,源码地址:https://github.com/xetorthio/jedis pom配置: <dependency>    <groupId ...

  7. [ PyQt入门教程 ] Qt Designer工具的布局管理

    这节课很重要..界面整洁美观与否就看布局了..这里讲布局方法,至于设计的天赋与最终界面的美感那就看造化了.. 本文主要讲述Qt Designer工具实现界面控件布局管理,就是排列组合控件.包括水平布局 ...

  8. Jmeter之CSS选择器/JQuery选择器关联

    选择器: CSS选择器或JQuery选择器是Jmeter支持的两种语法,下面对其两种语法进行简单介绍 CSS选择器 JQuery选择器 Chrome - 复制CSS选择器 Google Chrome在 ...

  9. PHP验证身份证格式

    互联网公司对身份证验证的需求越来越多,然而普通的小公司是无法对接公安部门的身份认证系统的.几乎都是在网上买一些大的互联网公司的一些认证服务.即使是便宜一些的认证价格也达到了10万次/万元.也就是一角钱 ...

  10. 中国地区表SQL语句

    /* Navicat MySQL Data Transfer Source Server : 本机 Source Server Version : 50553 Source Host : localh ...