技术框架中对高级查询一对多查询的学习

高级查询之一对多查询

查询条件

根据游戏名称,查询游戏账号信息

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

		/**
     * 根据游戏名查询游戏账号
     * @param name 游戏名
     * @return 游戏实体类
     */
    public GameEntity selectGameByName(String name);

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

关联查询方式

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

select g.*,a.* from tb_game as g join tb_account as a on g.id=a.game_id where g.name ='英雄联盟'

我们在数据库中执行这条 SQL 语句,结果如下:

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

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

public class GameEntity {
    private int id;
    private String name;
    private String type;
    private String operator;
    private List<AccountEntity> accounts; //关联引用游戏账号集合
}

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

你可能有疑惑,这里为何要使用 List 集合呢?原因是一款游戏对应的账号信息可能有多个,而 MyBatis 可以通过使用 resultMap 的 collection 标记将关联查询的多条记录映射到一个 List 集合属性中。

现在,我们来编写映射文件中 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="gameResultMap" type="entity.GameEntity">
        <id property="id" column="id" />
        <result property="name" column="name" />
        <result property="type" column="type" />
        <result property="operator" column="operator" />
      
       <!-- collection:一对多映射,关联当前分类下产品信息 
					  property:映射集合结果
					  ofType:结果集类型 -->
        <collection property="accounts" ofType="entity.AccountEntity">
            <id property="id" column="aid" />
            <result property="userName" column="user_name" />
            <result property="password" column="password" />
        </collection>
    </resultMap>
    <select id="selectGameByName" resultMap="gameResultMap">
        select g.*,a.id as aid,a.user_name,a.password from tb_game as g join tb_account as a on g.id=a.game_id where g.name =#{name}
    </select>
</mapper>

以上和一对一关联查询相比,association 标记改为 collection 标记,表示是一对多映射;javaType 属性改为ofType 属性,表示集合里的元素类型。除此以外,和一对一关联查询差不多。

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

	@Test
    public void selectGameByNameTest() {
        GameEntity gameEntity = gameMapper.selectGameByName("英雄联盟");
        System.out.println(gameEntity);

        Assert.assertNotNull(gameEntity);
    }

执行单元测试方法,结果如下:

2020-07-15 18:34:05,260 [main] [mapper.GameMapper.selectGameByName]-[DEBUG] ==>  Preparing: select g.*,a.* from tb_game as g join tb_account as a on g.id=a.game_id where g.name =? 
2020-07-15 18:34:05,307 [main] [mapper.GameMapper.selectGameByName]-[DEBUG] ==> Parameters: 英雄联盟(String)
2020-07-15 18:34:05,354 [main] [mapper.GameMapper.selectGameByName]-[DEBUG] <==      Total: 2
GameEntity{id=1, name='英雄联盟', type='MOBA', operator='腾讯游戏', accounts=[AccountEntity{id=1, userName='潇洒哥', password='12345'}, AccountEntity{id=4, userName='进击巨人', password='11111'}]}

子查询方式

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

select * from tb_account where game_id = (select id from tb_game where name ='英雄联盟')

接着,这里我们直接来编写映射文件中 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="gameResultMap" type="entity.GameEntity">
        <id property="id" column="id" />
        <result property="name" column="name" />
        <result property="type" column="type" />
        <result property="operator" column="operator" />
      
     		<!-- collection:用于映射关联查询多个对象信息
		         property:将关联查询的账号信息映射到属性 accounts 上
 						 column:传递子查询参数
						 select:子查询id
				-->
        <collection property="accounts" ofType="entity.AccountEntity"
            column="id" select="selectAccountById" />
    </resultMap>
  
    <select id="selectGameByName" resultMap="gameResultMap">
        select * from tb_game where name =#{name}
    </select>
    <select id="selectAccountById" resultType="entity.AccountEntity">
        select * from tb_account where game_id=#{gameId}
    </select>
</mapper>

执行测试,结果如下:

2020-07-15 21:25:11,086 [main] [mapper.GameMapper.selectGameByName]-[DEBUG] ==>  Preparing: select * from tb_game where name =? 
2020-07-15 21:25:11,164 [main] [mapper.GameMapper.selectGameByName]-[DEBUG] ==> Parameters: 英雄联盟(String)
2020-07-15 21:25:11,211 [main] [mapper.GameMapper.selectAccountById]-[DEBUG] ====>  Preparing: select * from tb_account where game_id=? 
2020-07-15 21:25:11,211 [main] [mapper.GameMapper.selectAccountById]-[DEBUG] ====> Parameters: 1(Integer)
2020-07-15 21:25:11,211 [main] [mapper.GameMapper.selectAccountById]-[DEBUG] <====      Total: 2
2020-07-15 21:25:11,211 [main] [mapper.GameMapper.selectGameByName]-[DEBUG] <==      Total: 1
GameEntity{id=1, name='英雄联盟', type='MOBA', operator='腾讯游戏', accounts=[AccountEntity{id=1, userName='潇洒哥', password='12345'}, AccountEntity{id=4, userName='进击巨人', password='11111'}]}
posted @ 2024-12-09 21:23  BingBing爱化学-04044  阅读(5)  评论(0编辑  收藏  举报