多表查询操作

Mybatis的多表操作

表之间的关系有几种:一对多、一对一、多对一、多对多
举例:
用户和订单就是一对多——一个用户可以下多个订单
订单和用户就是多对一——多个订单属于同一个用户

人和身份证号就是一对一
一个人只能有一个身份证号
一个身份证号只能属于一个人

老师和学生之间就是多对多
一个学生可以被多个老师教过
一个老师可以教多个学生
特例:
如果拿出每-一个订单,他都只能属于一个用户。
所以Mybatis就把多对一看成了一对一。

我们首先建立了两个新的表格方便操作,如下:
account表格:

user表格:

mybatis中的多表查询:

示例:用户和账户
一个用户可以有多个账户
一个账户只能属于一个用户(多个账户也可以属于同一个用户)

步骤:

  1. 建立两张表:用户表,账户表
    让用户表和账户表之间具备一对多的关系:需要使用外键在账户表中添加
    MySQL外键的作用:主要目的是控制存储在外键表中的数据。使两张表形成关联,外键只能引用外表中列的值!
    当创建或更改表时可通过定义 FOREIGN KEY 约束来创建外键
  2. 建立两个实体类:用户实体类和账户实体类
    让用户和账户的实体类能体现出啦一-对多的关系
  3. 建立两个配置文件
    用户的配置文件
    账户的配置文件
  4. 实现配置:
    当我们查询用户时,可以同时得到用户下所包含的账户信息
    当我们查询账户时,可以同时得到账户的所属用户信息

一对一操作

一.通过写Account子类的方式查询(不太常用)

    <!--查询所有账户同时包含用户名和地址信息--><select id="findAllAccount" resultType="accountuser">select a.*,u.username,u.address from account a , user uwhere u.id = a.uid;</select>

Account类

package com.domain;import java.io.Serializable;public class Account implements Serializable {private Integer id;private Integer uid;    //外键private Double money;public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public Integer getUid() {return uid;}public void setUid(Integer uid) {this.uid = uid;}public Double getMoney() {return money;}public void setMoney(Double money) {this.money = money;}@Overridepublic String toString() {return "Account{" +"id=" + id +", uid=" + uid +", money=" + money +'}';}
}

AccountUser类(Account子类)

package com.domain;public class AccountUser extends Account {        //继承了Account类private String username;private String address;public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getAddress() {return address;}public void setAddress(String address) {this.address = address;}@Overridepublic String toString() {return super.toString()+"        AccountUser{" +        //super.toString()调用父类的toString()方法"username='" + username + '\'' +", address='" + address + '\'' +'}';}
}

User类

package com.domain;import java.io.Serializable;
import java.util.Date;
import java.util.List;public class User implements Serializable {private Integer id;private String username;private String address;private String sex;private Date birthday;//一对多关系映射:主表实体应该包含从表实体的集合引用private List<Account> accounts;public List<Account> getAccounts() {return accounts;}public void setAccounts(List<Account> accounts) {this.accounts = accounts;}public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getAddress() {return address;}public void setAddress(String address) {this.address = address;}public String getSex() {return sex;}public void setSex(String sex) {this.sex = sex;}public Date getBirthday() {return birthday;}public void setBirthday(Date birthday) {this.birthday = birthday;}@Overridepublic String toString() {return "User{" +"id=" + id +", username='" + username + '\'' +", address='" + address + '\'' +", sex='" + sex + '\'' +", birthday=" + birthday +'}';}
}

测试类

    /*** 测试查询所有账户,同时包含用户名称和地址*/@Testpublic void testFindAllAccountUser(){List<AccountUser> aus = accountDao.findAllAccount();for(AccountUser au : aus){System.out.println(au);}}

结果:

大概思路
1.测试类findAllAccount()方法返回AccountUser集合,输出集合
2.执行findAllAccount()方法,转入xml配置文件,执行sql语句查询
3.返回AccountUser类型的查询结果,执行子类的toString方法
4.super.toString()执行父类的toString方法

二.通过建立实体类关系的方式(常用)

    <!-- 定义封装account和user的resultMap --><!-- 一对一的关系映射:配置封装user的内容--><resultMap id="accountUserMap" type="account"><id property="id" column="aid"/>    <!--此处的aid为表中id的别名--><result property="uid" column="uid"/><result property="money" column="money"/><association property="user" javaType="user">   <!--由于使用了别名,所以直接写user就行了--><!--为了防止我们开发出错,在没有特别要求的情况下,column名可以完全和property名称一致,否则当我们没有对应上的时候,数据库匹配不到--><id property="id" column="id"/><result column="username" property="username"/><result column="address" property="address"/><result column="sex" property="sex"/><result column="birthday" property="birthday"/></association></resultMap><!-- 查询所有 --><select id="findAll" resultMap="accountUserMap"><!-- as可理解为:用作、当成,作用;一般是重命名列名或者表名。(主要为了查询方便)-->select u.*,a.id as aid,a.uid,a.money from account a,user u where u.id = a.uid;</select>

association标签的作用:就是将另一张表的字段关联过来 然后一起映射到实体类

Account类(在之前的基础上改造)

package com.domain;import java.io.Serializable;public class Account implements Serializable {private Integer id;private Integer uid;    //外键private Double money;//从表实体应该包含一个主表实体的对象引用private User user;public User getUser() {return user;}public void setUser(User user) {this.user = user;}public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public Integer getUid() {return uid;}public void setUid(Integer uid) {this.uid = uid;}public Double getMoney() {return money;}public void setMoney(Double money) {this.money = money;}@Overridepublic String toString() {return "Account{" +"id=" + id +", uid=" + uid +", money=" + money +'}';}
}

User类(跟上面一样,不变)

测试类

    @Testpublic void testFindAll(){List<Account> accounts = accountDao.findAll();for(Account account : accounts){System.out.println("--------每个account的信息------------");System.out.println(account);System.out.println(account.getUser());//其实可以直接在Account类那里将toString()方法重写一遍,加上user,就不用调用getUser()方法了}}

结果:

一对多操作

一个用户存在多个账户的情况

    <!-- 定义User的resultMap--><!--一对多查询--><resultMap id="userAccountMap" type="user"><id property="id" column="id"/><result property="username" column="username"/><result property="address" column="address"/><result property="sex" column="sex"/><result property="birthday" column="birthday"/><!-- 配置user对象中accounts集合的映射 --><collection property="accounts" ofType="account">   <!--ofType指的是集合accounts的类型--><id column="aid" property="id"/>    <!--aid为列别名,起别名是因为主子表都有该字段--><result column="uid" property="uid"/><result column="money" property="money"/></collection></resultMap><!-- 查询所有 --><select id="findAll" resultMap="userAccountMap"><!-- left join(左联接)返回包括左表(user)中的所有记录和右表(account)中联结字段相等(即u.id = a.uid)的记录,即返回user表和满足u.id = a.uid条件的account表 -->select * from user u left outer join account a on u.id = a.uid</select>

注:

  • left join(左联接) 返回包括左表中的所有记录和右表中联结字段相等的记录
  • right join(右联接) 返回包括右表中的所有记录和左表中联结字段相等的记录
  • inner join(等值连接) 只返回两个表中联结字段相等的行
  • outer join(外连接) 可分为左外连接left outer join和右外连接right outer join

上面的left join(左联结)表示返回所有user表和满足u.id = a.uid条件的account表内容

User类(添加上了Account集合属性)

package com.domain;import java.io.Serializable;
import java.util.Date;
import java.util.List;public class User implements Serializable {private Integer id;private String username;private String address;private String sex;private Date birthday;//一对多关系映射:主表实体应该包含从表实体的集合引用private List<Account> accounts;public List<Account> getAccounts() {return accounts;}public void setAccounts(List<Account> accounts) {this.accounts = accounts;}public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getAddress() {return address;}public void setAddress(String address) {this.address = address;}public String getSex() {return sex;}public void setSex(String sex) {this.sex = sex;}public Date getBirthday() {return birthday;}public void setBirthday(Date birthday) {this.birthday = birthday;}@Overridepublic String toString() {return "User{" +"id=" + id +", username='" + username + '\'' +", address='" + address + '\'' +", sex='" + sex + '\'' +", birthday=" + birthday +'}';}
}

测试类

@Testpublic void testFindAll(){List<User> users = userDao.findAll();for(User user : users){System.out.println("-----每个用户的信息------");System.out.println(user);System.out.println(user.getAccounts());}}

结果:

多对多操作

示例:用户和角色
一个用户可以有多个角色
一个角色可以赋予多个用户

步骤:

  1. 建立两张表:用户表,角色表
    让用户表和角色表具有多对多的关系。需要使用中间表,中间表中包含各自的主键,在中间表中是外键。
  2. 建立两个实体类:用户实体类和角色实体类
    让用户和角色的实体类能体现出来多对多的关系
    各自包含对方一个集合引用
  3. 建立两个配置文件
    用户的配置文件
    角色的配置文件
  4. 实现配置:
    当我们查询用户时,可以同时得到用户所包含的角色信息
    当我们查询角色时,可以同时得到角色的所赋予的用户信息

1.查询角色获取角色下所包含的用户信息

    <!--定义role表的resultMap--><resultMap id="roleMap" type="role"><id property="roleId" column="rid"/><result property="roleName" column="role_name"/><result property="roleDesc" column="role_desc"/><collection property="users" ofType="user"><id column="id" property="id"/><result column="username" property="username"/><result column="address" property="address"/><result column="sex" property="sex"/><result column="birthday" property="birthday"/></collection></resultMap><!--查询所有--><select id="findAll" resultMap="roleMap">select u.*,r.id as rid,r.role_name,role_desc from role rleft outer join user_role ur on r.id=ur.ridleft outer join user u on u.id=ur.uid</select>

多对多查询的精华基本都在sql语句的书写上面了…

Role类

package com.domain;import java.io.Serializable;
import java.util.List;public class Role implements Serializable {private Integer roleId;private String roleName;private String roleDesc;private List<User> users;public List<User> getUsers() {return users;}public void setUsers(List<User> users) {this.users = users;}public Integer getRoleId() {return roleId;}public void setRoleId(Integer roleId) {this.roleId = roleId;}public String getRoleName() {return roleName;}public void setRoleName(String roleName) {this.roleName = roleName;}public String getRoleDesc() {return roleDesc;}public void setRoleDesc(String roleDesc) {this.roleDesc = roleDesc;}@Overridepublic String toString() {return "Role{" +"roleId=" + roleId +", roleName='" + roleName + '\'' +", roleDesc='" + roleDesc + '\'' +'}';}
}

User类

package com.domain;import java.io.Serializable;
import java.util.Date;public class User implements Serializable {private Integer id;private String username;private String address;private String sex;private Date birthday;public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getAddress() {return address;}public void setAddress(String address) {this.address = address;}public String getSex() {return sex;}public void setSex(String sex) {this.sex = sex;}public Date getBirthday() {return birthday;}public void setBirthday(Date birthday) {this.birthday = birthday;}@Overridepublic String toString() {return "User{" +"id=" + id +", username='" + username + '\'' +", address='" + address + '\'' +", sex='" + sex + '\'' +", birthday=" + birthday +'}';}
}

测试类

    @Testpublic void testFindAll(){List<Role> roles = roleDao.findAll();for(Role role : roles){System.out.println("-----每个角色的信息------");System.out.println(role);System.out.println(role.getUsers());}}

结果:

2.查询用户获取用户所包含的角色信息

    <!--多对多查询--><resultMap id="userMap" type="user"><id property="id" column="id"/><result property="username" column="username"/><result property="address" column="address"/><result property="sex" column="sex"/><result property="birthday" column="birthday"/><!--配置角色集合的映射--><collection property="roles" ofType="role"><id property="roleId" column="rid"/><result property="roleName" column="role_name"/><result property="roleDesc" column="role_desc"/></collection></resultMap><!-- 查询所有 --><select id="findAll" resultMap="userMap">select u.*,r.id as rid,r.role_name,role_desc from user uleft outer join user_role ur on u.id=ur.uidleft outer join role r on r.id=ur.rid</select>

通过观察我们可以发现UserDao的配置文件中的sql查询语句刚好是和上面查询角色时的反过来的。

Role类不变

User类(加上Role类型的集合属性)

package com.domain;import java.io.Serializable;
import java.util.Date;
import java.util.List;public class User implements Serializable {private Integer id;private String username;private String address;private String sex;private Date birthday;//多对多的关系映射:一个用户可以具备多个角色private List<Role>roles;public List<Role> getRoles() {return roles;}public void setRoles(List<Role> roles) {this.roles = roles;}public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getAddress() {return address;}public void setAddress(String address) {this.address = address;}public String getSex() {return sex;}public void setSex(String sex) {this.sex = sex;}public Date getBirthday() {return birthday;}public void setBirthday(Date birthday) {this.birthday = birthday;}@Overridepublic String toString() {return "User{" +"id=" + id +", username='" + username + '\'' +", address='" + address + '\'' +", sex='" + sex + '\'' +", birthday=" + birthday +'}';}
}

测试类

    @Testpublic void testFindAll(){List<User> users = userDao.findAll();for(User user : users){System.out.println("-----每个用户的信息------");System.out.println(user);System.out.println(user.getRoles());}}

Mybatis入门:4(多表查询操作)相关推荐

  1. mybatis 多表关联查询_Java修行第041天--MyBatis框架(下)--多表查询

    1 解决列名和属性名不一致问题 如果查询时使用 resultType 属性, 表示采用 MyBatis 的Auto-Mapping(自动映射)机制, 即相同的列名和属性名会自动匹配. 因此, 当数据库 ...

  2. 简单的单表和连表查询操作

    现在是做项目的时候,之前大部分都是跟着老师的视频和代码对着敲去完成老师的作业,做出了效果后就不管了,然后一段时间之后就不知道代码是怎样来的了,而且也不认识大部分的代码意思,现在做项目了,要自己去敲出来 ...

  3. yii mysql join_Yii框架连表查询操作示例

    本文实例讲述了Yii框架连表查询操作.分享给大家供大家参考,具体如下: Join //表连接 //查询出学生.班级.校区.记录表的所有数据 $data=Jf_record::find() ->j ...

  4. MyBatis如何实现多表查询

    MyBatis如何实现多表查询 先说结论,在MyBatis中我们有两种方式来实现多表查询 一.使用sqlmapper配置文件 二.使用注解 直入主题首先我们来看如何使用配置文件的方式来实现一对一,和一 ...

  5. 达梦数据库实验三:DMDBMS表查询操作

    目录标题 实验三 DMDBMS表查询操作 一.实验目的: 二.实验要求: 三.实验重点和难点: 四.实验内容: 五.实验步骤与结果: 1. 表创建 2. 数据填充 3. 数据查询 3.1查出选修了20 ...

  6. Mybatis入门程序增删改查操作

    学习目标 了解Mybatis的基本知识 熟悉Mybatis的工作原理 掌握Mybatis入门程序的编写 文章目录 1.初始Mybatis 2.Mybatis入门程序 3.Mybatis操作总结 1.初 ...

  7. MyBatis动态SQL_多表查询_延迟加载_缓存

    POJO包装传递对象 //POJO实体 public class QueryConditionObject {private User user;//user get,set方法 }//Dao 接口 ...

  8. C# 基于AE的GIS二次开发 要素查询操作,属性表查询操作及其属性表修改操作

    直接上代码: 要素查询 并高亮显示 模糊查询我的根据自己的表设计的,自己用基本语句是 属性表字段 LIKE '*内容*' *号为 SQL like语句里的% like '%%',在ArcGIS里是*开 ...

  9. 数据库的多表查询操作-查询只选修了1门课程的学生,显示学号、姓名、课程名。

    文章目录 前言 一.建立数据库和表 二.数据库展示 2.查询只选修了1门课程的学生,显示学号.姓名.课程名. 总结 前言 在我看来数据库真的是一个神奇的东西,不但里面的只是点很深刻,而且对于我们学习起 ...

最新文章

  1. Unity* 实体组件系统 (ECS)、C# 作业系统和突发编译器入门
  2. oracle数据库函数和存储过程的包
  3. 【SDOI2008】Sandy的卡片(后缀数组)
  4. Spring 异步调用,一行代码实现!舒服,不接受任何反驳~
  5. Java:自定义异常处理类
  6. 利用CentOS快速构建自己的发行版(3)
  7. 安装 ibm-java-x86_64-sdk-6.0-9.3.x86_64.rpm 的三步骤
  8. Android面向切面编程框架(AspectJ 讲解)
  9. 年度总结 | Flink 年度最佳学习路线总结
  10. android获取错误原因,从http读取数据时发生OutOfMemory错误获取请求android
  11. windows下python 自动截图功能
  12. iperf3 for Linux
  13. 线性代数 --- 什么是矩阵的逆?(个人笔记扫描版)
  14. ARM的启动过程详解(CHINAITLAB)
  15. 关于Chrome浏览器书签被更改的分析
  16. CodeForces703D Mishka and Interesting sum(树状数组)
  17. powerbi导入地图_PowerBI 地图 - 层级下钻形状地图最佳实践
  18. 踏歌智行筹备A股上市:正招募首席财务官,投资方包括宝通科技等
  19. 梁念坚漫步“云+端”
  20. 用C语言求奇数的几种方法

热门文章

  1. 【持续加精】几种强哥墙裂推荐的缓冲效果,各有千秋、各取所需
  2. 设置IDEA编辑过程直接通过F5刷新网页就可以实时查看JSP文件更新结果,而非通过重新run
  3. 如何将非官方扩展程序加入chrome的白名单
  4. Pip install: ImportError: cannot import name IncompleteRead
  5. 学习如何用平板电脑设计和绘制自己的动漫角色
  6. svn 提交信息模板
  7. 【D3】transition API
  8. 【Android动画】之Tween动画 (渐变、缩放、位移、旋转)
  9. 研究生要这样度过!(转)
  10. LAMP 关键数据集锦技术选项参考