MyBatis的多表查询

表之间的关系:一对多,多对一,一对一,多对多。

一对多:一个班级对应多个学生

多对一:多个学生对应一个班级

一对一:一个人对应一个身份证号码

多对多:一个订单可以有多个商品,一个商品也可以对应多个订单。

一对一

新建一个账户信息表:

其中ID是主键,UID对应于user表的id

需求:查询所有account表中的信息,并且包含对应的用户名和地址。

方式一(不常用):

新建账户类:

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;}public Account(Integer id, Integer uid, Double money) {this.id = id;this.uid = uid;this.money = money;}public Account() {}@Overridepublic String toString() {return "Account{" +"id=" + id +", uid=" + uid +", money=" + money +'}';}
}

由于只使用Account类只能包含账户信息,无法包含用户用户信息,因此新建一个类AccountUser继承与Account类:

public class AccountUser extends Account {private String username;private String address;@Overridepublic String toString() {return super.toString()+"   AccountUser{" +"username='" + username + '\'' +", address='" + 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;}
}

对应的xml文件:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="com.lwl.dao.IAccountDao"><!--查询所有--><select id="findAll" resultType="com.lwl.domain.Account">select * from account;</select><!--查询所有账户,包含用户名和地址--><select id="findAllAccount" resultType="com.lwl.domain.AccountUser">select a.*,u.username,u.address from account a, user u where u.id=a.uid;</select></mapper>

创建测试类进行测试:

public class AccountTest {private InputStream is;private SqlSession sqlSession;private IAccountDao accountDao;//初始化进行封装@Before //用于在测试方法执行之前执行public void init() throws Exception {//1.读取配置文件,形成字节输入流is = Resources.getResourceAsStream("SqlMapConfig.xml");//2.获取SqlSessionFactorySqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);//3.获取SqlSession对象sqlSession = factory.openSession();//4.获取dao的代理对象accountDao = sqlSession.getMapper(IAccountDao.class);}//close进行封装@After //用于在测试方法执行之后执行public void distory() throws Exception {//提交事务sqlSession.commit();//6.关闭资源sqlSession.close();is.close();}//查询所有账户@Testpublic void testFindAll(){List<Account> accounts = accountDao.findAll();for (Account account : accounts) {System.out.println(account);}}//查询所有账户,并包含用户名和地址@Testpublic void testFindAllAccount(){List<AccountUser> accountUsers = accountDao.findAllAccount();for (AccountUser accountUser : accountUsers) {System.out.println(accountUser);}}}

查询结果:

方式二:

使用resultMap,定义专门的resultMap用于映射一对一查询结果。 通过面向对象的关系可以得知,我们可以在Account类中加入一个User类的对象来代表这个账户是哪个用户的。

resultMap关键字

resultType

resultType可以把查询结果封装到pojo类型中,但必须pojo类的属性名和查询到的数据库表的字段名一致。
如果sql查询到的字段与pojo的属性名不一致,则需要使用resultMap将字段名和属性名对应起来,进行手动配置封装,将结果映射到pojo中。

<!-- resultMap最终还是要将结果映射到pojo上,type就是指定映射到哪一个pojo --><!-- id:设置ResultMap的id --><resultMap type="User" id="UserResultMap"><!-- property:pojo中的属性名 --><!-- column:对应在数据库中的列名 --><id property="id" column="id" /><!-- 定义普通属性 --><result property="name" column="username" /><result property="usersex" column="sex" /><result property="old" column="age" /><result property="address" column="address" /></resultMap>

resultMap可以实现将查询结果映射为复杂类型的pojo,比如在查询结果映射对象中包括pojo和list实现一对一查询和一对多查询。例如:

    <!--定义封装account和user的resultMap--><resultMap id="accountUserMap" type="com.lwl.domain.Account"><!--property为当前类的属性,即count类,column为主表数据库的列名,主键用id标签--><id property="id" column="id"></id><result property="uid" column="uid"></result><result property="money" column="money"></result><!--user属性属于另一个类的实例,需要进行映射--><!--association :一对一的关系映射,对user实例的内容进行封装--><!--property:是accout类中需要映射的user属性,column是其在user属性在count数据库中对应的表名,javaType是其user对应的类--><association property="user" column="uid" javaType="com.lwl.domain.User"><!--property为当前类的属性,column为主表数据库的列名,主键用id标签--><id property="id" column="id"></id><result property="username" column="username"></result><result property="address" column="address"></result><result property="sex" column="sex"></result></association></resultMap>

参考链接:https://blog.csdn.net/qq_42780864/article/details/81429114

修改Account类

从表实体应该包含一个主表的对象的实例

 重新定义AccountDao.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="com.lwl.dao.IAccountDao"><!--定义封装account和user的resultMap--><resultMap id="accountUserMap" type="com.lwl.domain.Account"><!--property为当前类的属性,column为主表数据库的列名,主键用id标签--><id property="id" column="id"></id><result property="uid" column="uid"></result><result property="money" column="money"></result><!--association :一对一的关系映射,配置user的内容,--><!--property:是accout类中user属性,column是其在数据库中对应的表名,javaType是其对应的类--><association property="user" column="uid" javaType="com.lwl.domain.User"><!--property为当前类的属性,column为主表数据库的列名,主键用id标签--><id property="id" column="id"></id><result property="username" column="username"></result><result property="address" column="address"></result><result property="sex" column="sex"></result><result property="age" column="age"></result><result property="email" column="email"></result><result property="qq" column="qq"></result></association></resultMap><!--查询所有--><select id="findAll" resultMap="accountUserMap">select a.*,u.* from account a, user u where u.id=a.uid;</select><!--查询所有账户,包含用户名和地址--><select id="findAllAccount" resultType="com.lwl.domain.AccountUser">select a.*,u.username,u.address from account a, user u where u.id=a.uid;</select></mapper>

在AccountTest类中加入测试方法

    //查询所有账户及用户信息@Testpublic void testFindAll(){List<Account> accounts = accountDao.findAll();for (Account account : accounts) {System.out.println(account);System.out.println(account.getUser());}}

一对多

修改count表的数据,使部分的user具有多个账户。

修改User对应,增加账户的集合属性,以及对应的get和set方法

    private List<Account> accounts;public List<Account> getAccounts() {return accounts;}public void setAccounts(List<Account> accounts) {this.accounts = accounts;}

创建IUserDao.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="com.lwl.dao.IUserDao"><!--定义User的resultMap--><resultMap id="userAccountMap" type="user"><id property="id" column="id"></id><result property="username" column="username"></result><result property="sex" column="sex"></result><result property="age" column="age"></result><result property="email" column="email"></result><result property="address" column="address"></result><result property="qq" column="qq"></result><!--配置user对象中accounts集合的映射--><collection property="accounts" ofType="com.lwl.domain.Account"><id property="id" column="aid"></id><result property="uid" column="uid"></result><result property="money" column="money"></result></collection></resultMap><!--查询所有--><select id="findAll" resultMap="userAccountMap">select * from user u left outer join account a on a.uid=u.id;</select>
</mapper>

创建测试类进行查询:


public class UserTest {private InputStream is;private SqlSession sqlSession;private IUserDao userDao;//初始化进行封装@Before //用于在测试方法执行之前执行public void init() throws IOException {//1.读取配置文件,形成字节输入流is = Resources.getResourceAsStream("SqlMapConfig.xml");//2.获取SqlSessionFactorySqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);//3.获取SqlSession对象sqlSession = factory.openSession();//4.获取dao的代理对象userDao = sqlSession.getMapper(IUserDao.class);}//close进行封装@After //用于在测试方法执行之后执行public void distory() throws IOException {//提交事务sqlSession.commit();//6.关闭资源sqlSession.close();is.close();}//测试查询所有@Testpublic void testFindAll(){//5.执行查询所有方法List<User> users = userDao.findAll();for (User user : users) {System.out.println(user);System.out.println(user.getAccounts());}}
}

多对多

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

创建数据库:

上面一个是role表。另一个是中间表,指定两表之间的关联。

创建角色Role类并提供set和get以及toString方法:

public class Role implements Serializable {private Integer roleId;private String roleName;private String roleDesc;//set和get略
}

创建相应Dao接口:

public interface IRoleDao {List<Role> findAll();
}

映射的xml文件:

注意类中的属性名和数据库中的列名不一样

    <resultMap id="roleMap" type="role"><id property="roleId" column="id"></id><result property="roleName" column="role_name"></result><result property="roleDesc" column="role_desc"></result></resultMap><!--查询所有--><select id="findAll" resultMap="roleMap">select * from role;</select>

进行查询测试:

public class RoleTest {private InputStream is;private SqlSession sqlSession;private IRoleDao roleDao;//初始化进行封装@Before //用于在测试方法执行之前执行public void init() throws IOException {//1.读取配置文件,形成字节输入流is = Resources.getResourceAsStream("SqlMapConfig.xml");//2.获取SqlSessionFactorySqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);//3.获取SqlSession对象sqlSession = factory.openSession();//4.获取dao的代理对象roleDao = sqlSession.getMapper(IRoleDao.class);}//close进行封装@After //用于在测试方法执行之后执行public void distory() throws IOException {//提交事务sqlSession.commit();//6.关闭资源sqlSession.close();is.close();}//测试查询所有@Testpublic void testFindAll(){List<Role> roles = roleDao.findAll();for (Role role : roles) {System.out.println(role);}}
}

接下来实现:
                当我们查询角色时,可以同时得到角色的所赋予的用户信息

在Role添加User的一个实例:

    private List<User> users;public List<User> getUsers() {return users;}public void setUsers(List<User> users) {this.users = users;}

在IRoleDao.xml中进行修改:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.lwl.dao.IRoleDao"><resultMap id="roleMap" type="role"><!--写成rid是因为在SQL语句中对id起了别名为rid--><id property="roleId" column="rid"></id><result property="roleName" column="role_name"></result><result property="roleDesc" column="role_desc"></result><collection property="users" ofType="user"><id column="id" property="id"></id><result column="username" property="username"></result><result column="address" property="address"></result><result column="sex" property="sex"></result><result column="birthday" property="birthday"></result></collection></resultMap><!--查询所有--><select id="findAll" resultMap="roleMap">select u.*,r.id as rid,r.role_name,r.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></mapper>

测试:

    //测试查询所有@Testpublic void testFindAll(){List<Role> roles = roleDao.findAll();for (Role role : roles) {System.out.println(role);System.out.println(role.getUsers());}}

接下来实现:
                当我们查询角色时,可以同时得到角色的所赋予的用户信息

修改SQL语句:

        select u.*,r.id as rid,r.role_name,r.role_desc from user uleft outer join user_role ur  on u.id = ur.uidleft outer join role r on r.id = ur.rid

在User表中添加Role的实例:

    private List<Role> roles;public List<Role> getRoles() {return roles;}public void setRoles(List<Role> roles) {this.roles = roles;}

配置xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="com.lwl.dao.IUserDao"><resultMap id="userMap" type="user"><!--写成rid是因为在SQL语句中对id起了别名为rid--><id column="id" property="id"></id><result column="username" property="username"></result><result column="address" property="address"></result><result column="sex" property="sex"></result><result column="birthday" property="birthday"></result><collection property="roles" ofType="role"><id property="roleId" column="rid"></id><result property="roleName" column="role_name"></result><result property="roleDesc" column="role_desc"></result></collection></resultMap><!--查询所有--><select id="findAll" resultMap="userMap">select u.*,r.id as rid,r.role_name,r.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></mapper>

进行测试:


/*** @author liwenlong* @data 2020/5/4*/
public class UserTest {private InputStream is;private SqlSession sqlSession;private IUserDao userDao;//初始化进行封装@Before //用于在测试方法执行之前执行public void init() throws IOException {//1.读取配置文件,形成字节输入流is = Resources.getResourceAsStream("SqlMapConfig.xml");//2.获取SqlSessionFactorySqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);//3.获取SqlSession对象sqlSession = factory.openSession();//4.获取dao的代理对象userDao = sqlSession.getMapper(IUserDao.class);}//close进行封装@After //用于在测试方法执行之后执行public void distory() throws IOException {//提交事务sqlSession.commit();//6.关闭资源sqlSession.close();is.close();}//测试查询所有@Testpublic void testFindAll(){//5.执行查询所有方法List<User> users = userDao.findAll();for (User user : users) {System.out.println(user);System.out.println(user.getRoles());}}
}

【MyBatis】多表查询相关推荐

  1. MyBatis多表查询之XML和注解实现(resultMap结果集映射配置数据库字段与实体类属性一一映射)

    MyBatis多表查询 多表模型分类 一对一:在任意一方建立外键,关联对方的主键. 一对多:在多的一方建立外键,关联一的一方的主键. 多对多:借助中间表,中间表至少两个字段,分别关联两张表的主键. 数 ...

  2. Mybatis—多表查询

    Mybatis多表查询 一对一查询 一对一查询的模型MapperScannerConfigurer 用户表和订单表的关系为,一个用户有多个订单,一个订单只从属于一个用户 创建Order和User实体 ...

  3. java day55【 Mybatis 连接池与事务深入 、 Mybatis 的动态 SQL 语句、 Mybatis 多表查询之一对多 、 Mybatis 多表查询之多对多】...

    第1章 Mybatis 连接池与事务深入 1.1 Mybatis 的连接池技术 1.1.1 Mybatis 连接池的分类 1.1.2 Mybatis 中数据源的配置 1.1.3 Mybatis 中 D ...

  4. mybatis多表查询(一对多,多对一,多对多)

    mybatis多表查询.多对一,一对多,多对多 多对一.一对多 准备阶段 建立dept实体类和emp实体类 建立Dao接口 写Dao的Mapper映射 多对多 多对一.一对多 准备阶段 建立一个部门表 ...

  5. 7. MyBatis多表查询 - 一对一 - 一对多 - 多对多

    7. MyBatis多表查询 - 一对一 - 一对多 - 多对多 前言 在前面的篇章,我们已经熟悉了单表查询,下面我们来看看如何进行 多表查询. 数据准备 create database if not ...

  6. Mybatis多表查询之一对多、多对一

    目录 前言 一.建立数据库 二.多对一查询 2.1 编写实体类 2.2 编写接口 2.3 编写Mapper配置文件 (StudentMapper.xml) 2.4 多对一查询结果 三.一对多查询 3. ...

  7. mybatis联表查询且统计数据

    mybatis联表查询且统计数据 表1的数据+表2的数据的统计==>vo接收 前端原型图如下: 涉及到两张表 t_record t_user_record 详情A/B A:未签收人数 B:全部人 ...

  8. 7.Mybatis关联表查询(这里主要讲的是一对一和一对多的关联查询)

    视频地址:http://edu.51cto.com/sd/be679 在Mybatis中的管理表查询这里主要介绍的是一对一和一对多的关联查询的resultMap的管理配置查询,当然你也可以用包装类来实 ...

  9. Mybatis学习笔记 4:Mybatis 连表查询(一)——一对多关系

    完整代码在这 在查询数据库时,我们经常会遇到多张表联合查询的情况,而Mybatis使连表查询更加简便了,查询出的数据格式非常易于使用,省去了一大部分复杂的代码编写工作,对于关系型数据库来说,数据模型之 ...

  10. mybatis多表查询出来的实体如何映射_mybatis进阶案例之多表查询

    mybatis进阶案例之多表查询 一.mybatis中表之间的关系 在数据库中,实体型之间的关系主要有如下几种: 1.一对一 如果对于实体集A中的每一个实体,实体集B中至多有一个(也可以没有)实体与之 ...

最新文章

  1. 给TreeView控件绑定数据
  2. JAVA怎么将整数反转_【leetcode刷题】[简单]7.反转整数(reverse integer)-java
  3. Swift - 将DaSwift-Data数据转换为[UInt8](bytes字节数组)
  4. centos通过yum的方式快速安装jdk1.8
  5. datacolumn 表达式 除数为0
  6. mysql计算3000分钟后的日期_MySQL – 计算两个日期时间之间的净时差,同时排除中断?...
  7. 不只是槓杆原理~~细说油压煞车
  8. 使用IDM的正确姿势
  9. matlab角度和弧度的互换_MATLAB弧度与角度转换
  10. 计算机桌面标题栏怎么锁定,(excel图表标题设置)在excel表格中,如何锁定标题栏不被修改?...
  11. C语言银行排队系统仿真
  12. AOP之5种增强方法应用范例
  13. 2021/7/15——集训Day.10
  14. 中国绿色PPP项目行业现状及发展建议:投资规模不断扩大,需要改善存在的问题,进一步推动绿色PPP健康发展[图]
  15. MySQL旧版本的完整卸载(最全面)
  16. 编译基于Chrome代码修改的Brave浏览器
  17. 华科教授因学生住宿问题投诉后勤处:被学校处分,取消两年评优资格
  18. [20181226]简单探究cluster table.txt
  19. 终极WordPress SEO初学者指南
  20. 【软工项目组】第三次会议(调研结果)

热门文章

  1. 百度 android 市场,百度Q2报告:Android市场份额21.4% 同比增长890%
  2. 拼多多直通车推广做好关键性的一步:商品标题如何引流?
  3. C++ 中ANSI/ASII/GB2312/Unicode/Utf-8编码的区别
  4. 投资:铁矿石研究框架
  5. 关于Flash Media Server
  6. 程序员进阶架构师、技术总监、CTO,需要掌握哪些核心技能
  7. QEMU中TCG翻译流程
  8. 超几何分布HyperGeometricDistribution
  9. 01_k8s入门----部署一个应用程序
  10. SQLI DUMB SERIES-6