MyBatis的关联查询

1.什么是关联查询

  • 实体间的关系(拥有 has、属于 belong)

    • OneToOne:一对一关系(account ←→ user)

    • OneToMany:一对多关系(user ←→ account)

    • ManyToMany:多对多关系(user ←→ role)

  • 什么是关联查询

    当访问关系的一方时,如果需要查看与之关联的另一方数据,则必须使用表链接查询,将查询到的另一方数据,保存在本方的属性中

  • 关联查询的语法

    指定“一方”关系时(对象),使用< association javaType="" >

    指定“多方”关系时(集合),使用< collection ofType="" >

  • Mybatis中的关联关系实现,主要通过resultMap来实现的

下面以案例的形式展现给大家 

2.一对一查询

需求:查询账户信息,关联查询用户信息。

分析:因为一个账户信息只能供某个用户使用,所以从查询账户信息出发关联查询用户信息为一对一查询。

数据表实现:通过A表的主键引用B表的主键作为外键,就是说在A中主键和外键同一字段。

数据库信息:

建立Account.java:

public class Account implements Serializable {

    private Integer id;
    private Integer uid;
    private Double money;
    //加入User类的对象作为Account类的一个属性
    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;
    }

    @Override
    public String toString() {
        return "Account{" +
                "id=" + id +
                ", uid=" + uid +
                ", money=" + money +
                ", user=" + user +
                '}';
    }
}

创建接口:

public interface AccountDao {
    List<Account> findAll();
}

xml文件:

<?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="com.by.mapper.AccountMapper">

    <resultMap id="getAccountByIdResult" type="com.by.pojo.Account">
        <id column="aid" property="id"></id>
        <result column="uid" property="uid"></result>
        <result column="money" property="money"></result>

        <!--
            一对一使用association标签指定数据的封装规则
            property="user":Account的属性名
            javaType="com.by.pojo.User":等价于resultType
        -->
        <association property="user" javaType="com.by.pojo.User">
            <id column="id" property="id"/>
            <result column="username" property="username"/>
            <result column="sex" property="sex"/>
            <result column="birthday" property="birthday"/>
            <result column="address" property="address"/>
        </association>
    </resultMap>

    <select id="getAccountById" parameterType="int" resultMap="getAccountByIdResult">
        SELECT a.id aid, a.uid uid, a.money money, u.* FROM account a LEFT JOIN user u ON a.uid=u.id WHERE a.id=#{id}
</mapper>

测试类:

    @Test
    public void testGetAccountById(){
        AccountMapper accountMapper = sqlSession.getMapper(AccountMapper.class);
        Account account = accountMapper.getAccountById(1);
        System.out.println(account);
    }

3.一对多查询

需求:查询所有用户信息及用户关联的账户信息。

分析:用户信息和他的账户信息为一对多关系,并且查询过程中如果用户没有账户信息,此时也要将用户信息查询出来,此时左外连接查询比较合适。

数据表实现:使用一个外键进行关联,外键放在多方的表中;

创建user,一对一用可以对象,一对多时可以使用集合来代表多的一方:

package com.by.pojo;

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 password;
    private Date birthday;
    private String sex;
    private String address;
    //加入List<Account>存储用户所拥有的账户
    private List<Account> 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 Date getBirthday() {
        return birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public List<Account> getAccounts() {
        return accounts;
    }

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

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                ", birthday=" + birthday +
                ", sex='" + sex + '\'' +
                ", address='" + address + '\'' +
                ", accounts=" + accounts +
                '}';
    }
}

创建接口:

 public interface AccountDao {  
  List<Account> findAll();
}

通过resultMap进行结果映射,collection标签可以指定映射的集合,其中porperty属性指定的是该关联属性的名称,ofType指定的是集合里面的java类型,id,result标签同resultMap中的一样是对集合里面的属性进行映射;

创建xml:

<mapper namespace="com.by.mapper.UserMapper">

    <resultMap id="getUserByIdResult" type="com.by.pojo.User">
        <id column="id" property="id"></id>
        <result column="username" property="username"/>
        <result column="address" property="address"/>
        <result column="sex" property="sex"/>
        <result column="birthday" property="birthday"/>

        <!--一堆多使用collection标签指定数据的封装规则-->
        <collection property="accountList" ofType="com.by.pojo.Account">
            <id column="aid" property="id"></id>
            <result column="uid" property="uid"></result>
            <result column="money" property="money"></result>
        </collection>
    </resultMap>

    <select id="getUserById" parameterType="int" resultMap="getUserByIdResult">
        SELECT u.*, a.id aid, a.uid uid, a.money money FROM user u LEFT JOIN account a ON u.id=a.uid WHERE u.id=#{id}
    </select>

测试类:

  /**
     * 一对多:一个user 对 多个Account
     */
    @Test
    public void testGetUserById(){
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        User user = userMapper.getUserById(41);
        System.out.println(user);
    }

3.多对多查询

需求:查询角色及角色赋予的用户信息。

分析:一个用户可以拥有多个角色,一个角色也可以赋予多个用户,用户和角色为双向的一对多关系,多对多关系其实我们看成是双向的一对多关系。

数据表:需要用一张中间表表示多对多的关系,这张中间表引入两张表的主键作为外键;

①多表连接查询,不需要定义中间表实体类
②多表嵌套查询,需要定义中间表实体类
③多表复杂查询,不需要定义中间表实体类,但是返回值是一个List;

多表嵌套查询定义中间实体类:


由于两张表之间分别单独查询,需要通过中间表查找关联并使用resultMap进行映射关系处理,resultMap需要指明映射的java的类,并在实体类中定义关联属性才可以得到关联属性的信息;简单来说:一张表查询完之后想要得到另一张表的信息,实际上是通过中间表来进行映射得到另一张表的信息的;

多表复杂查询:通过一张表先和中间表进行连接查询,然后再查询另一张表的信息;

数据库:

创建Role:

public class Role {
    private Integer id;
    private String roleName;
    private String roleDesc;

    //多方
    private List<User> userList;

创建接口:

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

创建xml:

<mapper namespace="com.by.mapper.RoleMapper">

    <resultMap id="getRoleByIdResultMap" type="com.by.pojo.Role">
        <id column="rid" property="id"></id>
        <result column="role_name" property="roleName"></result>
        <result column="role_desc" property="roleDesc"></result>

        <!--
            一对多使用collection标签指定数据的封装规则
            property="userList":pojo的属性
            ofType="com.by.pojo.User":集合的泛型,等价于resultType
        -->
        <collection property="userList" ofType="com.by.pojo.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="getRoleById" parameterType="int" resultMap="getRoleByIdResultMap">
        SELECT
            r.id as rid,r.role_name,r.role_desc,
            u.*
        FROM
            user_role ur
                JOIN role r ON ur.rid=r.id
                JOIN user u ON ur.uid=u.id
        WHERE
            r.id=#{id}
    </select>
</mapper>

创建测试类:

    /**
     * 多对多:一个user 对 多个role   一个role 对 多个user
     */
    @Test
    public void testGetRoleById(){
        RoleMapper roleMapper = sqlSession.getMapper(RoleMapper.class);
        Role role = roleMapper.getRoleById(1);
        System.out.println(role);
    }

  • 19
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MyBatis关联查询是指在查询数据库时,通过配置映射文件,将多个表之间的关联数据查询出来并进行组合。可以使用嵌套结果映射或嵌套查询来处理关联查询。 在嵌套结果映射中,可以使用\<resultMap>来定义映射关系,并使用\<association>来设置关联对象。例如,可以定义一个resultMap来映射Classes和Teacher表之间的关联关系,然后通过联表查询将两个表的数据关联起来。 另一种方式是使用嵌套查询,即在映射文件中通过\<select>标签设置嵌套查询语句来获取关联数据。通过联表查询获取到的数据可以作为嵌套查询的参数,从而获取到关联数据。 以上就是MyBatis关联查询的基本概念和使用方式。可以根据具体的需求选择合适的方式进行关联查询操作。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [SSM框架的学习与应用-Java EE企业级应用开发学习记录(第四天)Mybatis的关联映射和缓存机制](https://download.csdn.net/download/m0_53659738/88253127)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [mybatis关联查询](https://blog.csdn.net/faramita_of_mine/article/details/122202515)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值