高级查询之一对一查询

查询条件:根据游戏角色ID,查询账号信息

我们在之前创建的映射器接口 GameMapper.java 中添加接口方法,如下:

		/**
* 根据角色ID查询账号信息
* @param id 角色Id
* @return 角色实体对象
*/
public RoleEntity selectRoleById(int id);

接下来,我分别演示关联查询和子查询方式实现接口方法的映射。

关联查询方式:

现在我们暂时先抛开 MyBatis 框架,直接从数据库出发写一写关联查询的 SQL 语句,如下:

select r.*,a.* from tb_role as r join tb_account as a on r.account_id=a.id where r.id=1

另外,还有一种不使用 join 关键字的 SQL 语句写法,如下:

select r.*,a.* from tb_role as r,tb_account as a where r.account_id=a.id and r.id=1

第一种写法,使用 join 关键字,本质上是采用的内连接(inner join)。

第二种写法,不使用 join 关键字,本质上是采用交叉连接(cross join),也即生成两表的笛卡尔积,得到的记录相当于两表记录的乘积。

以上两种写法查询结果是相同的,但推荐使用第一种,因为第一种性能比第二种高,特别是在有大表的情况下。

理由是第二种交叉连接将产生更多的记录,然后通过 where 后的 r.account_id=a.id 条件过滤不需要的记录,而第一种内连接会直接过滤不需要的记录,所以执行效率更高。

我们执行一下查询结果,如下:

现在,我们回到 MyBatis 框架,看一下在 XML 映射文件中,如何实现关联查询映射。

首先,我们需要建立 RoleEntity 实体类与 AccountEntity 实体类之间的关联关系,如下:

public class RoleEntity {
private int id;
private String profession;
private int rank;
private int money;
private AccountEntity account; //关联引用属性
...
}

这样,通过账号名查询的账号信息就可以映射到 account 属性中。注意 account 属性的 get 和 set 方法要记得添加上去,还有 toString 方法要重写一下,添加 account 属性的打印信息。

现在,我们来编写映射文件中 SQL 语句映射,如下:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="mapper.GameMapper">
<resultMap id="roleResultMap" type="entity.RoleEntity">
<id property="id" column="id" />
<result property="profession" column="profession" />
<result property="rank" column="rank" />
<result property="money" column="money" />
<!-- association:用于映射关联查询单个对象信息
property:将关联查询的账号信息映射到属性 account 上 -->
<association property="account" javaType="entity.AccountEntity">
<id property="id" column="id" />
<result property="userName" column="user_name" />
<result property="password" column="password" />
</association>
</resultMap> <select id="selectRoleById" resultMap="roleResultMap">
select r.*,a.* from tb_role as r join tb_account as a on r.account_id=a.id where r.id=#{id}
</select>
</mapper>

和之前单表映射相比,没什么太大差别,就是多了 association 子标记以及相应的内容罢了。

意思很也简单,就是将关联查询结果中的账号信息,具体而言就是 a.id,a.user_name,a.password ,映射到 AccountEntity 实例中,也就是 RoleEntity.account 属性。

最后,我们在 MyBatisTest 中添加一个单元测试方法,如下:

		@Test
public void selectRoleByAccountNameTest() {
RoleEntity roleEntity = gameMapper.selectRoleById(1);
System.out.println(roleEntity); Assert.assertNotNull(roleEntity);
}

执行测试,结果如下:

2020-07-15 10:49:28,860 [main] [mapper.GameMapper.selectRoleById]-[DEBUG] ==>  Preparing: select r.*,a.id,a.user_name,a.password from tb_role as r join tb_account as a on r.account_id=a.id where r.id=?
2020-07-15 10:49:28,954 [main] [mapper.GameMapper.selectRoleById]-[DEBUG] ==> Parameters: 1(Integer)
2020-07-15 10:49:28,985 [main] [mapper.GameMapper.selectRoleById]-[DEBUG] <== Total: 1
RoleEntity{id=1, profession='战士', rank=10, money=2000, account=AccountEntity{id=1, userName='潇洒哥', password='12345'}}

这样,我们通过游戏角色ID查询到了游戏账号信息,并封装在 RoleEntity 对象的 account 属性中。

最新文章

  1. python学习笔记(基础一:&#39;hello world&#39;、变量、字符编码)
  2. C#温故知新:《C#图解教程》读书笔记系列
  3. 加快FineReport报表设计的几个心得体会
  4. 第二百二十六天 how can I 坚持
  5. HDU 3586 Information Disturbing (二分+树形dp)
  6. Storm中的LocalState 代码解析
  7. 在IOS开发中,属性名为id的处理方法
  8. a/b + c/d
  9. [译]Selenium Python文档:五、Waits等待
  10. C# 扩展方法使用
  11. 17-Flink消费Kafka写入Mysql
  12. 使用session统计在线人数
  13. npm 离线安装依赖
  14. mysql 开发进阶篇系列 20 MySQL Server(innodb_lock_wait_timeout,innodb_support_xa,innodb _log_*)
  15. sqlalchem表关联(一对多,一对一,多对多)
  16. Ubuntu16.04 安装Processing
  17. smarty学习——基本概念
  18. Flask从入门到精通之Flask-Moment本地化日期和时间
  19. 8-16 不无聊序列 non-boring sequences uva1608
  20. mysql批量insert速度超慢

热门文章

  1. 「SpringBoot2.4新特性」jar自动瘦身
  2. Day02_13_Javadoc_生成帮助文档
  3. Json文件转换为Excel文件!涉及读文件,时间戳转化,写文档
  4. python 匿名函数,内置函数
  5. Springboot+Vue前后端分离的博客项目
  6. C++介绍和class的介绍
  7. C - 抽屉 POJ - 3370 (容斥原理)
  8. 032- for循环语句
  9. 【日志追踪】(微服务应用和单体应用)-logback中的MDC机制
  10. PAT 乙级 -- 1012 -- 数字分类