MyBatis学习笔记5-多表查询

多表查询准备工作,新建了三个表。之前使用的user表,新建的role表,account表,user_role表。表中具体参数如下:

user表(主要是表头,内容自行填充):
在这里插入图片描述

role表:
在这里插入图片描述
account表:
在这里插入图片描述
user_role表:
在这里插入图片描述
这些类创建好之后,记得在domain中创建其实体类,并重写set,get,toString方法,然后在dao接口中写这三个类的接口,其余步骤前面已经说过,这里不再赘述。展示一下目录结构,有的文件我已经建好了(AccountUser,User2),后面才要用,到时候用的时候再解释
在这里插入图片描述

表之间的关系有多种,分别有一对一,一对多,多对一,多对多。

例如:

  • 人和身份证号就是一对一,一个人只能有一个身份证号,一个身份证号只能属于一个人
  • 用户和订单就是一对多,订单和用户就是多对一。一个用户可以下多个订单,多个订单属于同一个用户。
  • 老师和学生之间就是多对多,一个学生可以被多个老师教过,一个老师可以交多个学生
    简单起见,只实现一对一,一对多(多对一和一对多原理一样,学习一个即可)和多对多的功能。

1.一对一(这里介绍的方法是配置文件的方法进行一对一,继承类一对一虽然简单,但是不常用,故跳过不提)

主要实现的SQL语句:

select a.*,u.* from account a,user u where a.uid=u.id;

首先在IAccountDao中提供方法

List <Account> findAccountAndUser();

查出来很简单,这里把查出来的结果封装起来。我们将结果封装到Account类中,因此在Account中需要加入User属性(private User user),就是多表实体类中维护的单表实体类对象。更重要的是,需要在IAccountDao.xml中添加配置文件,在mapper标签中配置,主要配置文件如下:

<mapper namespace="dao.IAccountDao">
    <resultMap id="accountMap" type="account">
<!--        配置主键-->
        <id property="id" column="id"/>
        <result property="uid" column="uid"/>
        <result property="money" column="money"/>
        <association property="user" column="uid" javaType="user">
<!--            配置主键-->
            <id property="id" column="id"/>
            <result property="username" column="username"/>
            <result property="password" column="password"/>
            <result property="sex" column="sex"/>
            <result property="address" column="address"/>
        </association>
    </resultMap>

这个我们之前配置表中名和属性名时的配置一样,不同的是,这次我们在后面加了一个association标签,这个标签主要和user产生关联,下面解释一下association中这几个属性的含义:

  • property=“user” 实体类中维护的单表实体类对象
  • column=“uid” 多表通过这个uid字段跟单表产生关联
  • javaType=“user” 通过账户查询出信息,封装到User类中, 前面配置过别名,所有直接写user

配置完成之后,直接在下面写sql语句。需要注意的是,需要引用上面的“accountMap”,否则就白配置了

<select id="findAccountAndUser" resultMap="accountMap">
        select a.*,u.* from account a,user u where a.uid=u.id;
</select>

到这里,主要工作就做完啦,最后写个测试文件测试一下就OK了。呐,这是我的测试文件

@Test
    public void testFindAccountAndUser(){
        List<Account> user = dao.findAccountAndUser();
        for (Account account : user) {
            System.out.println(account);
        }
    }

最终结果是正确的,这里就不进行演示了。

2.一对多

和一对一不同的是,我们在进行一对多的结果封装时,需要在单表实体类中提供一个集合,来描述这个一对多的关系,集合里面装的就是多个用户。
先看一下主要查询语句:

select u.*,a.id as aid,a.uid,a.money from user u left join account a on a.uid=u.id;

在此语句中,就是user用户要展示完,对应的账户表有则展示,没有展示null即可。当然了,这就是要把结果封装到user实体类中了,不过这次我们在user中添加的属性,是一个集合,如下:

private List<Account> accounts;

记得补全get,set,toString方法哦

下来就是在单表实体类IUserDao.xml映射文件中进行配置,和之前一样,我们也在resultMap标签中进行配置,先上代码

<resultMap id="userMap" type="user">
        <id property="id" column="id"/>
        <result property="username" column="username"/>
        <result property="password" column="password"/>
        <result property="sex" column="sex"/>
        <result property="address" column="address"/>
        <collection property="accounts" ofType="account">
            <id property="id" column="aid"/>
<!--            在查询中,我们用a.id as aid,所以上面column中写aid-->
            <result property="uid" column="uid"/>
            <result property="money" column="money"/>
        </collection>
    </resultMap>

不同的是,这次我们在里面使用的是collection标签,下面解释一下collection中两个属性名的含义:

  • property=“accounts” 主表实体类中维护的那个集合
  • ofType=“account” 集合中封装的类型

然后,我们在下面接着写SQL语句就好了,如下:

<select id="findAccountAndUser" resultMap="userMap">
        select u.*,a.id as aid,a.uid,a.money from user u left join account a on a.uid=u.id;
    </select>

记得,一定要写resultMap。最后写一个测试文件测试一下就好了。测试代码如下:

//    一对多测试
    @Test
    public void testFindAccountAndUser(){
        List<User> list = dao.findAccountAndUser();
        for (User user : list) {
            System.out.println(user);

        }
}

结果就省略了,亲测没毛病。

3.多对多

先看一下最终的SQL语句:

select r.id as rid,r.role_name,r.role_desc,u.* from role r left outer join user_role ur on r.id=ur.rid left outer join user u on ur.uid=u.id;

简单解释一下,用三张表,role表,user表和user_role表,user_role表是中间表,其uid和user表产生联系,rid和role表产生联系,最终使role和user表产生联系。这个多对多分种,就是看把查询出来的结果封装到哪个实体类中,我这里封装到了role类中。其实原理都一样,有兴趣的伙伴可以试着封装到user类中。

之前的user类中已经添加属性了,我这里就不改了,免得之前的测试功能坏掉,这里我们新建一个user2类,还是要保留之前的属性。既然我们要将结果封装到role中,就要在role类中添加属性,如下:

@Getter
@Setter
@ToString
public class Role implements Serializable {
    private Integer id;
    private String roleName;
    private String roleDesc;
//  这里的属性名和表中的字段名有点不一样,所以一会要配置映射
    private List<User2> user2s;
}

我这里使用了Lombok插件,自动补全了get,set,toString方法。并且,roleName,roleDesc和表中的名字不太一样(表中是role_name,role_desc),一会配置就好了。

然后在IRoleDao接口中添加方法

//    外连接查找角色和用户表
    List<Role> findByRoleAndUser();

接下来就在IRoleDao.xml配置文件中进行配置,主要配置如下:

<resultMap id="roleMap" type="Role">
<!--    配置主键-->
        <id property="id" column="id"/>
<!--    配置其余属性-->
        <result property="roleName" column="role_name"/>
        <result property="roleDesc" column="role_desc"/>
<!--        此种配置,测出来的是每个角色对应的用户信息,换句话说,角色信息都有,用户信息可能不全-->
        <collection property="user2s" ofType="user2">
            <id property="id" column="id"></id>
            <result property="username" column="username"></result>
            <result property="password" column="password"></result>
            <result property="sex" column="sex"></result>
            <result property="address" column="address"></result>
        </collection>
    </resultMap>

我们这里使用的标签是collection,和一对多的一样,里面的属性就不解释啦,下来写SQL语句即可

<select id="findByRoleAndUser" resultMap="roleMap" resultType="role">
        select r.id as rid,r.role_name,r.role_desc,u.* from role r left outer join user_role ur on r.id=ur.rid left outer join user u on ur.uid=u.id;
</select>

然后写测试代码:

@Test
    public void testFindByRoleAndUser(){
        List<Role> roles = dao.findByRoleAndUser();
        for (Role role : roles) {
            System.out.println(role);
        }
}

展示一下结果吧,要不有人说我在这瞎写呢
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值