Mybatis 多表查询示例(多对多查询)

  • 示例:用户和角色
    • 一个用户可以有多个角色
    • 一个角色可以赋予多个用户
  • 需求:实现Role到User多对多
  • 步骤:
    • 1、建立两张表:用户表,角色表
      • 让用户表和角色表具有多对多的关系。需要使用中间表,中间表中包含各自的主键,在中间表中是外键。
    • 2、建立两个实体类:用户实体类和角色实体类
      • 让用户和角色的实体类能体现出多对多的关系
      • 各自包含对方一个集合引用
    • 3、建立两个配置文件
      • 用户的peizhiwenjian
      • 角色的配置文件
    • 4、实现配置
      • 当我们查询用户时,可以同时得到用户所包含的角色信息
      • 当我们查询角色时,可以同时得到角色的所赋予的用户信息

数据库脚本

DROP TABLE IF EXISTS `user`;

CREATE TABLE `user` (
  `id` int(11) NOT NULL auto_increment,
  `username` varchar(32) NOT NULL COMMENT '用户名称',
  `birthday` datetime default NULL COMMENT '生日',
  `sex` char(1) default NULL COMMENT '性别',
  `address` varchar(256) default NULL COMMENT '地址',
  PRIMARY KEY  (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;



insert  into `user`(`id`,`username`,`birthday`,`sex`,`address`) values (41,'老王','2018-02-27 17:47:08','男','北京'),(42,'小二王','2018-03-02 15:09:37','女','北京金燕龙'),(43,'小二王','2018-03-04 11:34:34','女','北京金燕龙'),(45,'传智播客','2018-03-04 12:04:06','男','北京金燕龙'),(46,'老王','2018-03-07 17:37:26','男','北京'),(48,'小马宝莉','2018-03-08 11:44:00','女','北京修正');


DROP TABLE IF EXISTS `role`;

CREATE TABLE `role` (
  `ID` int(11) NOT NULL COMMENT '编号',
  `ROLE_NAME` varchar(30) default NULL COMMENT '角色名称',
  `ROLE_DESC` varchar(60) default NULL COMMENT '角色描述',
  PRIMARY KEY  (`ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;



insert  into `role`(`ID`,`ROLE_NAME`,`ROLE_DESC`) values (1,'院长','管理整个学院'),(2,'总裁','管理整个公司'),(3,'校长','管理整个学校');


DROP TABLE IF EXISTS `user_role`;

CREATE TABLE `user_role` (
  `UID` int(11) NOT NULL COMMENT '用户编号',
  `RID` int(11) NOT NULL COMMENT '角色编号',
  PRIMARY KEY  (`UID`,`RID`),
  KEY `FK_Reference_10` (`RID`),
  CONSTRAINT `FK_Reference_10` FOREIGN KEY (`RID`) REFERENCES `role` (`ID`),
  CONSTRAINT `FK_Reference_9` FOREIGN KEY (`UID`) REFERENCES `user` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

insert  into `user_role`(`UID`,`RID`) values (41,1),(45,1),(41,2);

用户和角色的关系模型

  •  
  • 在数据库添加用户表、角色表和中间表

实现 Role User 多对多

业务要求及实现SQL

  • 需求:实现查询所有角色并且加载它所分配的用户信息
  • 分析:查询角色我们需要用到Role表,但根据Role表我们并不能直接找到用户信息,而是要通过中间表(USER_ROLE表)才能关联用户信息。

  • 下面是SQL语句:

  • SELECT
    	r.*,u.id uid,
    	u.username username,
    	u.birthday birthday,
    	u.sex sex,
    	u.address address
    FROM
    	role r
    INNER JOIN
    	user_role ur
    on (r.id=ur.rid)
    INNER join
    	user u
    on (ur.uid=u.id);
  • 执行结果

编写角色实体类

@Data
@ToString
public class Role implements Serializable {
    private Integer roleId;
    private String roleName;
    private String roleDesc;

    //多对多的关系映射:一个角色可以赋予多个用户
    private List<User> users;

    @Override
    public String toString() {
        return "Role{" +
                "roleId=" + roleId +
                ", roleName='" + roleName + '\'' +
                ", roleDesc='" + roleDesc + '\'' +
                '}';
    }
}

编写Role持久层接口

public interface IRoleDao {

    /**
     * 查询所有角色
     * @return
     */
    List<Role> findAll();
}

编写映射文件

<?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="cn.tedu.dao.IRoleDao">
    <!--定义role表的ResultMap-->
    <resultMap id="roleMap" type="cn.tedu.pojo.Role">
        <id property="roleId" column="id"></id>
        <id property="roleName" column="role_name"></id>
        <id property="roleDesc" column="role_desc"></id>
        <!--配置role对象中user集合的映射-->
        <collection property="users" ofType="cn.tedu.pojo.User">
            <id column="uid" 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="findAll" resultMap="roleMap">
        SELECT
            r.*,u.id uid,
            u.username username,
            u.birthday birthday,
            u.sex sex,
            u.address address
        FROM
            role r
        INNER JOIN
            user_role ur
        on (r.id=ur.rid)
        INNER join
            user u
        on (ur.uid=u.id);
    </select>
</mapper>

编写测试类

public class RoleTest {

    private InputStream in;
    private SqlSession session;
    IRoleDao roleDao;

    @Before//用于在测试方法执行之前执行
    public void init() throws IOException {
        //1.读取配置文件
        in = Resources.getResourceAsStream("mybatis-config.xml");
        //2.创建SqlSessionFactory工厂
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        SqlSessionFactory factory = builder.build(in);
        //3.使用工厂生产SqlSession对象
        session = factory.openSession();
        //4.使用SqlSession创建Dao接口的代理对象
        roleDao = session.getMapper(IRoleDao.class);
    }

    @After//用于在测试方法执行之后执行
    public void destory() throws IOException {
        //提交事务
        session.commit();
        //6.释放资源
        session.close();
        in.close();
    }

    /**
     * 测试查询所有
     */
    @Test
    public void testFindAll() {
        List<Role> roles =roleDao.findAll();
        for (Role role : roles) {
            System.out.println("-------每个role的信息-------");
            System.out.println(role);
            System.out.println(role.getUsers());
        }
    }
}

执行结果

实现 User Role 的多对多

编写User实体类

@Data
@ToString
public class User {
    private Integer id;
    private String username;
    private String address;
    private String sex;
    private Date birthday;

    //多对多的关系映射:一个用户可以有多个角色
    private List<Role> roles;
    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", address='" + address + '\'' +
                ", sex='" + sex + '\'' +
                ", birthday=" + birthday +
                '}';
    }
}

编写User持久层接口

/**
 * 用户的持久层接口
 */
public interface IUserDao {
    /**
     * 查询所有用户,同时获取到用户下所有账户的信息
     * @return
     */
    List<User> findAll();

    /**
     * 根据id查询
     * @param id
     * @return
     */
    User findById(Integer id);
}

编写映射文件

<?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="cn.tedu.dao.IUserDao">

    <!--定义User的resultMap-->
    <resultMap id="userMap" type="cn.tedu.pojo.User">
        <id property="id" column="uid"></id>
        <result property="username" column="username"></result>
        <result property="address" column="address"></result>
        <result property="sex" column="sex"></result>
        <result property="birthday" column="birthday"></result>
        <collection property="roles" ofType="cn.tedu.pojo.Role">
            <id column="id" property="roleId"></id>
            <id column="role_name" property="roleName"></id>
            <id column="role_desc" property="roleDesc"></id>
        </collection>
    </resultMap>

    <!--查询所有-->
    <select id="findAll" resultMap="userMap">
        SELECT
            u.id uid,
            u.username username,
            u.birthday birthday,
            u.sex sex,
            u.address address,
            r.*
        FROM
            user u
        LEFT JOIN
            user_role ur
        on (u.id=ur.uid)
        LEFT join
            role r
        on (ur.rid=r.id);
    </select>

    <!--根据id查询-->
    <select id="findById" resultType="cn.tedu.pojo.User" parameterType="int">
        SELECT * FROM user WHERE id=#{id}
    </select>

</mapper>

编写测试类

public class UserTest {

    private InputStream in;
    private SqlSession session;
    IUserDao userDao;

    @Before//用于在测试方法执行之前执行
    public void init() throws IOException {
        //1.读取配置文件
        in = Resources.getResourceAsStream("mybatis-config.xml");
        //2.创建SqlSessionFactory工厂
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        SqlSessionFactory factory = builder.build(in);
        //3.使用工厂生产SqlSession对象
        session = factory.openSession();
        //4.使用SqlSession创建Dao接口的代理对象
        userDao = session.getMapper(IUserDao.class);
    }

    @After//用于在测试方法执行之后执行
    public void destory() throws IOException {
        //提交事务
        session.commit();
        //6.释放资源
        session.close();
        in.close();
    }

    /**
     * 测试查询所有
     */
    @Test
    public void testFindAll() {
        List<User> users =userDao.findAll();
        for (User user : users) {
            System.out.println("-----每个用户的信息------");
            System.out.println(user);
            System.out.println(user.getRoles());
        }
    }
}

执行结果

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值