【MyBatis】多表查询
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】多表查询相关推荐
- MyBatis多表查询之XML和注解实现(resultMap结果集映射配置数据库字段与实体类属性一一映射)
MyBatis多表查询 多表模型分类 一对一:在任意一方建立外键,关联对方的主键. 一对多:在多的一方建立外键,关联一的一方的主键. 多对多:借助中间表,中间表至少两个字段,分别关联两张表的主键. 数 ...
- Mybatis—多表查询
Mybatis多表查询 一对一查询 一对一查询的模型MapperScannerConfigurer 用户表和订单表的关系为,一个用户有多个订单,一个订单只从属于一个用户 创建Order和User实体 ...
- 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 ...
- mybatis多表查询(一对多,多对一,多对多)
mybatis多表查询.多对一,一对多,多对多 多对一.一对多 准备阶段 建立dept实体类和emp实体类 建立Dao接口 写Dao的Mapper映射 多对多 多对一.一对多 准备阶段 建立一个部门表 ...
- 7. MyBatis多表查询 - 一对一 - 一对多 - 多对多
7. MyBatis多表查询 - 一对一 - 一对多 - 多对多 前言 在前面的篇章,我们已经熟悉了单表查询,下面我们来看看如何进行 多表查询. 数据准备 create database if not ...
- Mybatis多表查询之一对多、多对一
目录 前言 一.建立数据库 二.多对一查询 2.1 编写实体类 2.2 编写接口 2.3 编写Mapper配置文件 (StudentMapper.xml) 2.4 多对一查询结果 三.一对多查询 3. ...
- mybatis联表查询且统计数据
mybatis联表查询且统计数据 表1的数据+表2的数据的统计==>vo接收 前端原型图如下: 涉及到两张表 t_record t_user_record 详情A/B A:未签收人数 B:全部人 ...
- 7.Mybatis关联表查询(这里主要讲的是一对一和一对多的关联查询)
视频地址:http://edu.51cto.com/sd/be679 在Mybatis中的管理表查询这里主要介绍的是一对一和一对多的关联查询的resultMap的管理配置查询,当然你也可以用包装类来实 ...
- Mybatis学习笔记 4:Mybatis 连表查询(一)——一对多关系
完整代码在这 在查询数据库时,我们经常会遇到多张表联合查询的情况,而Mybatis使连表查询更加简便了,查询出的数据格式非常易于使用,省去了一大部分复杂的代码编写工作,对于关系型数据库来说,数据模型之 ...
- mybatis多表查询出来的实体如何映射_mybatis进阶案例之多表查询
mybatis进阶案例之多表查询 一.mybatis中表之间的关系 在数据库中,实体型之间的关系主要有如下几种: 1.一对一 如果对于实体集A中的每一个实体,实体集B中至多有一个(也可以没有)实体与之 ...
最新文章
- 给TreeView控件绑定数据
- JAVA怎么将整数反转_【leetcode刷题】[简单]7.反转整数(reverse integer)-java
- Swift - 将DaSwift-Data数据转换为[UInt8](bytes字节数组)
- centos通过yum的方式快速安装jdk1.8
- datacolumn 表达式 除数为0
- mysql计算3000分钟后的日期_MySQL – 计算两个日期时间之间的净时差,同时排除中断?...
- 不只是槓杆原理~~细说油压煞车
- 使用IDM的正确姿势
- matlab角度和弧度的互换_MATLAB弧度与角度转换
- 计算机桌面标题栏怎么锁定,(excel图表标题设置)在excel表格中,如何锁定标题栏不被修改?...
- C语言银行排队系统仿真
- AOP之5种增强方法应用范例
- 2021/7/15——集训Day.10
- 中国绿色PPP项目行业现状及发展建议:投资规模不断扩大,需要改善存在的问题,进一步推动绿色PPP健康发展[图]
- MySQL旧版本的完整卸载(最全面)
- 编译基于Chrome代码修改的Brave浏览器
- 华科教授因学生住宿问题投诉后勤处:被学校处分,取消两年评优资格
- [20181226]简单探究cluster table.txt
- 终极WordPress SEO初学者指南
- 【软工项目组】第三次会议(调研结果)
热门文章
- 百度 android 市场,百度Q2报告:Android市场份额21.4% 同比增长890%
- 拼多多直通车推广做好关键性的一步:商品标题如何引流?
- C++ 中ANSI/ASII/GB2312/Unicode/Utf-8编码的区别
- 投资:铁矿石研究框架
- 关于Flash Media Server
- 程序员进阶架构师、技术总监、CTO,需要掌握哪些核心技能
- QEMU中TCG翻译流程
- 超几何分布HyperGeometricDistribution
- 01_k8s入门----部署一个应用程序
- SQLI DUMB SERIES-6