SSM学习之路——Mybatis第三天_多表查询相关

前置工作

创建一张account表和user表
user表:
在这里插入图片描述account表:
在这里插入图片描述
外键uid对应user表中的id
在这里插入图片描述
插入数据:uid可以重复,表示一个用户可能有多个账户(卡)
在这里插入图片描述

一、查询所有的账户信息(及对应用户)

(1)创建账户表的持久接口

1、目录结构如下
在这里插入图片描述
2、接口代码如下

public interface IAccountDao {
    /**
     * 查找account账户信息以及所对应的用户信息的 姓名,地址
     * @return
     */
    List<Account> findAll();
}

(2)创建java实体类Account

目录结构如下
在这里插入图片描述
代码如下
值得注意的是这里创建一个User对象,用于返回对应的user的信息
其它即根据数据表中字段创建相同的java字段名,也生成get&set&tostring

public class Account implements Serializable {
    private Integer id;
    private Integer uid;
    private Double money;

    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类中代码(省去了相应的get&set)
在这里插入图片描述

(3)重点,编写xml文件

1、创建xml文件IAcountDao.xml
在这里插入图片描述
2、编写xml,代码如下
type对应的是account实体类,数据要封装到这个实体类中

<id property="id" column="aid"></id>,由于下面sql语句将a.id as aid,所以这里account类中的id需要对应的列名为aid

这里引入了<association>标签,请看注释

<?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.itheima.dao.IAccountDao">
    <resultMap id="accountUserMap" type="account">
        <!--这一行的column为aid是因为,在下面查询语句,执行了 a.id as aid 的操作,所以这里对应的数据库字段应该为aid-->
        <id property="id" column="aid"></id>
        <result property="uid" column="uid"></result>
        <result property="money" column="money"></result>
        <!--这里property应该为与account相关联的表,column为account中与property处的表关联的数据库字段(外键),字段类型来自于java里面的user类 ,对应javaType-->
        <association property="user" column="uid" javaType="user">
            <id property="id" column="uid"></id>
            <result property="username" column="username"></result>
            <result property="birthday" column="birthday"></result>
            <result property="sex" column="sex"></result>
            <result property="address" column="address"></result>
        </association>
    </resultMap>
    <select id="findAll" resultMap="accountUserMap">
    select u.*,a.id as aid,a.uid,a.money from account a,user u where u.id=a.uid
    </select>
</mapper>

其中,通过sql语句可以发现,这里用了a.id as aid的取别名做法。

原因是,account表中有id,对应的账户的id(可以理解为卡号),user表中也有id,对应用户的id,通过观察表可以发现,其实account表中的id为大写的ID,为什么会冲突呢,因为mysql语句在windows系统下不区分大小写,所以视为这两个是一样的。如果不加这个,在查询的时候数据库会为我们自动创建一个列名为ID1的列对应account的id列。如下图。

新建查询:
在这里插入图片描述
可以看到上图,账户对应的id列名已经变成了id(1)
为了更好的控制列名,我们直接将a.id命名为aid。

(4)编写测试类

通过accountDao.findAll()来获取所有的账户放在Account类对象集合中
通过getUser来拿到对应的用户信息。

public class MybatisTest {
    InputStream in;
    private SqlSessionFactory factory;
    SqlSession session;
    IAccountDao accountDao;
    @Before
    public void init() throws IOException {
        //1.获取配置文件流
        in = Resources.getResourceAsStream("SqlMapConfig.xml");
        //2.创建SqlSessionFactory工厂
        factory = new SqlSessionFactoryBuilder().build(in);
        //3.用工厂创建一个SqlSession
        session = factory.openSession();
        //4.用SqlSession创建一个Dao接口的代理
        accountDao = session.getMapper(IAccountDao.class);
    }
    @After
    public void destroy() throws IOException{
        session.commit();
        session.close();
        in.close();
    }
    @Test
    public void testFindAll(){
        List<Account> accounts = accountDao.findAll();
        for (Account account:accounts){
            System.out.println("------one data-------");
            System.out.println(account);
            System.out.println(account.getUser());
        }
    }
}

运行一下测试类:
可以看到,account表中的数据全有了,并且也打印出了每个账户所对应的用户信息。
在这里插入图片描述

二、查询用户信息并打印该用户的所有账户

(1)在IUserDao接口中添加方法

findAllUserAndAccounts(); 返回一个用户列表
在这里插入图片描述

(2)对User实体类做相应改造

为每个用户添加一个Account列表,用于储存该用户所有账户,并生成get&set
在这里插入图片描述

(3)编写xml文件

值得注意的为:(详细看注释)
此处的<collection>标签的各个属性
以及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="com.itheima.dao.IUserDao">

    <resultMap id="userAndAccountMap" type="user">
        <id property="id" column="id"></id>
        <result property="username" column="username"></result>
        <result property="birthday" column="birthday"></result>
        <result property="sex" column="sex"></result>
        <result property="address" column="address"></result>
        <!--配置user对象中的accounts集合的映射-->
        <!--一个集合标签,property为集合名,ofType表示集合里面是什么类型的对象,没起别名的时候ofType应该为全限定类名-->
        <collection property="accounts" ofType="account">
            <id property="id" column="aid"></id>
            <result property="uid" column="uid"></result>
            <result property="money" column="money"></result>
        </collection>
    </resultMap>
    
    <select id="findAllUserAndAccounts" resultMap="userAndAccountMap">
    <!--采用左表外连接 显示所有user的同时也显示他们的accounts-->
        select *,a.id as aid from user u left outer join account a on u.id=a.uid
    </select>
</mapper>

(4)编写test类

因为上一个例子用了把原来的MybatisTest中的代理改成account的代理了,这里方便起见重新创建一个类
在这里插入图片描述

public class TestUserAndAccount {
    InputStream in;
    private SqlSessionFactory factory;
    SqlSession session;
    IUserDao userDao;
    @Before
    public void init() throws IOException {
        //1.获取配置文件流
        in = Resources.getResourceAsStream("SqlMapConfig.xml");
        //2.创建SqlSessionFactory工厂
        factory = new SqlSessionFactoryBuilder().build(in);
        //3.用工厂创建一个SqlSession
        session = factory.openSession();
        //4.用SqlSession创建一个Dao接口的代理
        userDao = session.getMapper(IUserDao.class);
    }
    @After
    public void destroy() throws IOException{
        session.commit();
        session.close();
        in.close();
    }
    @Test
    public void testFindAll(){
        List<User> users = userDao.findAllUserAndAccounts();
        for (User user:users) {
            //只获取有账户信息的用户,并打印其所有账户信息
            if (user.getAccounts().size() > 0) {
                System.out.println("-------one data---------");
                System.out.println(user);
                System.out.println(user.getAccounts());
            }
        }
    }
}

运行结果:

在这里插入图片描述
妹毛病嗷铁汁!

前置工作(二)

(1)新建一张表role,存放角色信息

在这里插入图片描述
(2)创建一张中间表uer_role来存放user和role的关系的关系,其中rid对应角色的id,uid对应user的id
在这里插入图片描述

一、查询一个用户对应的所有角色

(1)新建IUserDao接口类

在这里插入图片描述

public interface IUserDao {
    List<User> findAll();
}

(2)新建Role实体类并在User类里添加相应内容

编写与数据库内容对应的字段名,并且生成相应的set&get&toString
(这里字段和数据库的字段不统一,所以在下面编写xml的时候要写一个resultMap映射)

在这里插入图片描述
在User类中添加Role集合,并生成相应的set&get

    private List<Role> roles;

(3)编写IUserDao.xml文件

详细的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="com.itheima.dao.IUserDao">
    <!--编写对应的结果映射,映射字段到user实体类中-->
    <resultMap id="userRoleMap" type="user">
        <id property="id" column="id"></id>
        <result property="username" column="username"></result>
        <result property="birthday" column="birthday"></result>
        <result property="sex" column="sex"></result>
        <result property="address" column="address"></result>
        <!--对User类中的Role集合实体类进行映射,property为集合类型,ofType为对应的实体类名-->
        <collection property="roles" ofType="role" >
            <id property="roleId" column="role_id"></id>
            <result property="roleName" column="role_name"></result>
            <result property="roleDesc" column="role_desc"></result>
        </collection>
    </resultMap>

    <select id="findAll" resultMap="userRoleMap">
        <!--采用左表外连接,
        先用user表 左表外连接中间表(当user的id == user_role表中的uid)
        再用上面已经取得的结果表
        结果表 左表外连接角色表(当role的id == 中间表对应的rid )
        由此两个表都对应起来,拿到了user对应的角色信息
        -->
        select u.*,r.* from user u
         left outer join user_role ur on u.id = ur.uid
         left outer join role r on r.role_id = ur.rid
    </select>
</mapper>

(4)编写测试类

在这里插入图片描述

package com.itheima.test;

import com.itheima.dao.IUserDao;
import com.itheima.domain.User;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;

public class UserRoleTest {
    private InputStream in;
    private SqlSessionFactory factory;
    private SqlSession session;
    IUserDao userDao;
    @Before
    public void init() throws IOException {
        in = Resources.getResourceAsStream("SqlMapConfig.xml");
        factory = new SqlSessionFactoryBuilder().build(in);
        session = factory.openSession();
        userDao = session.getMapper(IUserDao.class);
    }
    @After
    public void destroy () throws IOException {
        session.commit();
        in.close();
    }
    @Test
    public void testUserRoles(){
        List<User> users = userDao.findAll();
        for (User user:users){
        //为了方便显示,这里只打印有角色信息的用户
                if (user.getRoles().size() > 0){
                    System.out.println("-------one data------");
                    System.out.println(user);
                    System.out.println(user.getRoles());
                }
        }
    }
}

运行结果:
可以看到,id为75和id为76,角色均是副校长,而且id为75同时还是数学老师
在这里插入图片描述

二、查询一个角色对应的所有用户信息

(1)新建IRoleDao接口类

在这里插入图片描述

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

(2)Role实体类新增字段

添加一个User集合,用来存放该角色下的所有用户信息

在这里插入图片描述

(3)新建xml文件

在这里插入图片描述
xml文件与上文类似
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="com.itheima.dao.IRoleDao">
    <resultMap id="roleMap" type="role">
        <id property="roleId" column="role_id"></id>
        <result property="roleName" column="role_name"></result>
        <result property="roleDesc" column="role_desc"></result>
        <collection property="users" ofType="user">
            <id property="id" column="id"></id>
            <result property="username" column="username"></result>
            <result property="birthday" column="birthday"></result>
            <result property="sex" column="sex"></result>
            <result property="address" column="address"></result>
        </collection>
    </resultMap>
    <select id="findAll" resultMap="roleMap">
        select * from role r
         left outer join user_role ur on ur.rid = r.role_id
         left outer join user u on u.id = ur.uid

    </select>
</mapper>

(4)编写测试类

新建测试类
在这里插入图片描述

package com.itheima.test;

import com.itheima.dao.IRoleDao;
import com.itheima.domain.Role;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;

public class RoleUserTest {
    private InputStream in;
    private SqlSessionFactory factory;
    private SqlSession session;
    IRoleDao roleDao;
    @Before
    public void init() throws IOException {
        in = Resources.getResourceAsStream("SqlMapConfig.xml");
        factory = new SqlSessionFactoryBuilder().build(in);
        session = factory.openSession();
        roleDao = session.getMapper(IRoleDao.class);
    }
    @After
    public void destroy () throws IOException {
        session.commit();
        in.close();
    }
    @Test
    public void testUserRoles(){
        List<Role> roles = roleDao.findAll();
        for (Role role:roles){
            if (role.getUsers().size() > 0){
                System.out.println("-------one data------");
                System.out.println(role);
                System.out.println(role.getUsers());
            }
        }
    }
}

运行结果:
可以看到,也表明了有两个副校长。分别为id为75和76的用户
与上一块内容的结果对应起来了。
在这里插入图片描述
关于mybatis的多表查询相关入门到此告一段落。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值