【Mybatis 学习】Mybatis 多表查询之一对一查询

一、借助一个中间表实现一对一查询

需求:查询所有账户信息,关联查询下单用户信息。
注意:因为一个账户信息只能供某个用户使用,所以从查询账户信息出发关联查询用户信息为一对一查询。如果从用户信息出发查询用户下的账户信息则为一对多查询,因为一个用户可以有多个账户

(1)定义账户信息的实体类

@Data
public class Account {
    private Integer id;
    private Integer uid;
    private Double money;
}

(2)定义AccountUser 类相当于中间表封装了账户信息也封装了用户信息
为了能够封装上面 SQL 语句的查询结果,定义 AccountCustomer 类中要包含账户信息同时还要包含用户信息,所以我们要在定义 AccountUser 类时可以继承 Account 类。

@Data
public class AccountUser extends Account {
    private String username;
    private String address;

    @Override
    public String toString() {
        return super.toString() + "  AccountUser{" +
                "username='" + username + '\'' +
                ", address='" + address + '\'' +
                '}';
    }
}

(3)定义account 的 Dao 接口

public interface AccountDao {
    /**
     * 查询所有账户,并且带有用户名称和地址信息
     * @return
     */
    List<AccountUser> findAllAccount();
}

(4)定义 AccountDao.xml 文件的查询配置信息

<mapper namespace="mybatis.dao.AccountDao">

    <!--查询所有用户-->
    <select id="findAllAccount" resultType="accountUser">
        select a.*,u.username,u.address from account a,user u where a.uid = u.id;
    </select>
</mapper>

二、使用 ResultMap 实现一对一查询

(1)修改 Account 类

@Data
public class Account {
    private Integer id;
    private Integer uid;
    private Double money;
    /**
     * 从表实体应该包含一个主表实体的对象引用
     */
    private User user;
}

也就是,账户信息中添加了对应的用户信息
(2)修改AccountDao 接口中的方法

public interface AccountDao {
    /**
     * 查询所有账户,同时还要获取到当前账户的所属用户信息
     * @return
     */
    List<Account> findAll();
}

这里的返回值是 Account类型,因为 Account 类中包含了一个User类的对象,它可以封装账户所对应的用户信息
(3)重新定义 AccountDao.xml 文件

<mapper namespace="mybatis.dao.AccountDao">
    <!--定义封装account和user的resultMap-->
    <resultMap id="accountUserMap" type="account">
        <id property="id" column="id"></id>
        <result property="uid" column="uid"></result>
        <result property="money" column="money"></result>
        <!--一对一的关系映射:配置封装 user 的内容-->
        <!--property对应的实体类的属性,javaType 对应的是封装到哪个对象,由于已经在SqlMapConfig.xml起了别名所以可以直接使用类名-->
        <association property="user" javaType="user">
            <id property="id" column="id"></id>
            <result property="username" column="username"></result>
            <result property="sex" column="sex"></result>
            <result property="birthday" column="birthday"></result>
            <result property="address" column="address"></result>
        </association>
    </resultMap>
    <!--查询账户信息-->
    <select id="findAll" resultMap="accountUserMap">
       select u.*,a.* from account a,user u where a.uid=u.id;
    </select>
</mapper>

这里注意 <id property="id" column="id"></id>,property 对应的是实体类的属性名,这里也就是 account.java 中的属性,column 对应的是数据库查询所得的列名。
在这里插入图片描述
所以如果在查询语句中为查询的结果起了别名的话,这里就要做相应的修改,比如select查询语句的返回结果中为 id 起别名为aid:

在这里插入图片描述
其他不换,aid别名即为账户的id数据返回时对应的列名,所以在resultMap 封装时也要做好对应关系,这里之所以起别名是因为数据库account表和user 表都存在id字段,不用别名分开,会造成混乱

同时也需注意,一对一的映射关系使用的是 association

<!-- 它是用于指定从表方的引用实体属性的 -->
<association property="user" javaType="user">
</association>

三、分布查询实现多对一(一对一)

分步查询的优点:可以实现延迟加载,但是必须在核心配置文件中设置全局配置信息

比如现在有学生表 stu,班级表class
stu:
在这里插入图片描述
班级表:
在这里插入图片描述
现在想查询学生信息,以及班级名称

public interface StuMapper {
    /**
     * 通过分步查询查询学生以及学生所对应的班级信息
     * 分步查询第一步:查询学生信息
     */
    Student getStuAndClassByStepOne(@Param("sid") Integer sid);
}
<resultMap id="stuAndClassByStepResultMap" type="student">
    <id property="sid" column="sid"></id>
    <result property="sname" column="sname"></result>
    <result property="score" column="score"></result>
    <!--
        select:设置分步查询的sql的唯一标识(namespace.SQLId或mapper接口的全类名.方法名)
        column:设置分布查询的条件
        fetchType:当开启了全局的延迟加载之后,可通过此属性手动控制延迟加载的效果
        fetchType="lazy|eager":lazy表示延迟加载,eager表示立即加载
    -->
    <association property="aClass"
                 select="com.atguigu.mybatis.mapper.ClassMapper.getEmpAndDeptByStepTwo"
                <!--以查询结果中的哪个字段作为第二步的查询条件(是数据库中的字段)-->
                 column="classid"
                 fetchType="eager"></association>
</resultMap>

<!--Student getStuAndClassByStepOne(@Param("sid") Integer sid);-->
<select id="getStuAndClassByStepOne" resultMap="stuAndClassByStepResultMap">
    select * from stu where sid = #{sid}
</select>
public interface ClassMapper {
    /**
     * 通过分步查询查询学生以及学生所对应的班级信息
     * 分步查询第二步:通过classid查询学生所对应的班级
     */
    StuClass getStuAndClassByStepTwo(@Param("cid") Integer cid);
}
	<!--StuClass getEmpAndDeptByStepTwo(@Param("cid") Integer cid);-->
    <select id="getEmpAndDeptByStepTwo" resultType="StuClass">
        select * from class where cid = #{cid}
    </select>

在这里插入图片描述

  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

南淮北安

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值