MyBatis多表联查

前言


创建数据库表(user和message),并插入数据:

CREATE TABLE `user` (

`id`  varchar(64) NOT NULL ,

`name`  varchar(64) NULL ,

PRIMARY KEY (`id`)

);

CREATE TABLE `info` (

`id`  varchar(64) NOT NULL ,

`uid`  varchar(64) NULL ,

`msg`  varchar(255) NULL ,

PRIMARY KEY (`id`)

);

INSERT INTO `user` (`id`, `name`) VALUES ('1001', 'ahzoo');

INSERT INTO `user` (`id`, `name`) VALUES ('1002', 'ouo');

INSERT INTO `info` (`id`, `uid`, `msg`) VALUES ('2001', '1001', '测试信息');

INSERT INTO `info` (`id`, `uid`, `msg`) VALUES ('2002', '1001', '第二条信息');

再创建两个数据库表(role和user_role),并插入数据,用于多对多操作:

CREATE TABLE `role` (

`id`  varchar(64) NOT NULL ,

`name`  varchar(64) NULL ,

PRIMARY KEY (`id`)

);

CREATE TABLE `user_role` (

`user_id`  varchar(64) NOT NULL ,

`role_id`  varchar(64) NOT NULL

);

INSERT INTO `role` (`id`, `name`) VALUES ('3001', '用户');

INSERT INTO `role` (`id`, `name`) VALUES ('3002', '管理员');

INSERT INTO `user_role` (`user_id`, `role_id`) VALUES ('1001', '3001');

INSERT INTO `user_role` (`user_id`, `role_id`) VALUES ('1001', '3002');

INSERT INTO `user_role` (`user_id`, `role_id`) VALUES ('1002', '3002');

创建一个springboot项目,并生成增删改查,快速开始。

项目结构:

依赖:

<dependencies>

        <dependency>

            <groupId>mysql</groupId>

            <artifactId>mysql-connector-java</artifactId>

        </dependency>

        <dependency>

            <groupId>org.mybatis.spring.boot</groupId>

            <artifactId>mybatis-spring-boot-starter</artifactId>

            <version>2.2.2</version>

        </dependency>

        <dependency>

            <groupId>org.springframework.boot</groupId>

            <artifactId>spring-boot-starter</artifactId>

        </dependency>

        <dependency>

            <groupId>org.projectlombok</groupId>

            <artifactId>lombok</artifactId>

            <optional>true</optional>

        </dependency>

        <dependency>

            <groupId>org.springframework.boot</groupId>

            <artifactId>spring-boot-starter-test</artifactId>

            <scope>test</scope>

        </dependency>

    </dependencies>

一对一

一条信息对应一个发送者,查询信息的发送者。在Info实体类中增加User对象,这样在对user和info进行联查时,将User对象一起返回:entity/Info

import lombok.Data;

@Data

public class Info {

    private String id;

    private String uid;

    private String msg;

//    接收一对一查询到的User对象

    private User user;

}

映射文件:mapper/InfoDao.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.example.demo.mapper.InfoMapper">

<!--    使用Map对象作为返回结果-->

    <select id="selectListToMap" resultType="Map">

        SELECT u.id,u.name,i.id,i.uid,i.msg

        FROM user u,info i

        WHERE u.id=i.uid

    </select>

    <resultMap id="BaseResultMap" type="com.example.demo.entity.Info">

        <id property="id" column="id" jdbcType="VARCHAR"/>

        <result property="uid" column="uid" jdbcType="VARCHAR"/>

        <result property="msg" column="msg" jdbcType="VARCHAR"/>

        <association property="user" javaType="com.example.demo.entity.User">

持久层:mapper/InfoMapper

import com.example.demo.entity.Info;

import org.apache.ibatis.annotations.Mapper;

import java.util.List;

import java.util.Map;

@Mapper

public interface InfoMapper {

    List<Map<String,String>> selectListToMap();

    List<Info> selectListByMap();

}

测试:查询目标信息对应的用户信息

import com.example.demo.entity.Info;

import com.example.demo.mapper.InfoMapper;

import org.junit.jupiter.api.Test;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.boot.test.context.SpringBootTest;

import java.util.List;

import java.util.Map;

@SpringBootTest

class InfoTests {

    @Autowired

    InfoMapper infoMapper;

    /**

    * 使用Map对象作为返回结果

    */

    @Test

    public void toGetMapResult(){

        List<Map<String, String>> infos = infoMapper.selectListToMap();

        infos.forEach(System.out::println);

        /*

        {msg=测试信息, uid=1001, name=ahzoo, id=1001}

        {msg=第二条信息, uid=1001, name=ahzoo, id=1001}

        */

    }

    /**

    * 使用Info对象作为返回结果

    */

    @Test

    public void toGetInfoResult(){

        List<Info> infos = infoMapper.selectListByMap();

        infos.forEach(System.out::println);

        /*

        Info(id=2001, uid=1001, msg=测试信息, user=User(id=1001, name=ahzoo))

        Info(id=2002, uid=1001, msg=第二条信息, user=User(id=1001, name=ahzoo))

        */

    }

}

一对多

一个用户可以发送多条信息,查询用户下的所有信息。在User实体类中增加Info的List对象,用于返回查询到的多个Info对象:entity/User

import lombok.Data;

import java.util.List;

@Data

public class User{

    private String id;

    private String name;

//    接收一对多查询到的Info对象集合

    private List<Info> infos;

}

持久层:mapper/UserMapper

import com.example.demo.entity.User;

import org.apache.ibatis.annotations.Mapper;

import java.util.List;

@Mapper

public interface UserMapper {

    List<User> findAllByMap();

}

映射文件:mapper/UserMapper.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.example.demo.mapper.UserMapper">

    <resultMap id="BaseResultMap" type="com.example.demo.entity.User">

        <id property="id" column="id" jdbcType="VARCHAR"/>

        <result property="name" column="name" jdbcType="VARCHAR"/>

        <!--配置集合信息

        property:自定义集合的名称

        ofType:集合的数据类型

        -->

        <collection property="infos" ofType="com.example.demo.entity.Info">

            <result property="id" column="info_id" jdbcType="VARCHAR"/>

            <result property="uid" column="uid" jdbcType="VARCHAR"/>

            <result property="msg" column="msg" jdbcType="VARCHAR"/>

        </collection>

    </resultMap>

    <!-- 查询目标用户所有发布的信息(这里使用左外连接查询) -->

    <select id="findAllByMap" resultMap="BaseResultMap">

        SELECT u.id,u.name,i.id AS info_id,i.uid,i.msg

        FROM user u

        LEFT OUTER JOIN info i

            ON u.id = i.uid;

    </select>

</mapper>

测试:

import com.example.demo.entity.User;

import com.example.demo.mapper.UserMapper;

import org.junit.jupiter.api.Test;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.boot.test.context.SpringBootTest;

import java.util.List;

@SpringBootTest

public class UserTests {

    @Autowired

    UserMapper userMapper;

    @Test

    public void toGetAll(){

        List<User> allByMap = userMapper.findAllByMap();

        allByMap.forEach(System.out::println);

        /*

        User(id=1001, name=ahzoo, infos=[Info(id=2001, uid=1001, msg=测试信息, user=null), Info(id=2002, uid=1001, msg=第二条信息, user=null)])

        */

    }

}

可以看到所有用户下的所有信息都被查询到

多对多

一个用户可以有多个角色,一个角色可以属于多个用户,查询用户对应的角色,及角色对应的用户。在User实体类中增加Role的List对象,用于返回查询到的多个Role对象:entity/User

import lombok.Data;

import java.util.List;

@Data

public class User{

    private String id;

    private String name;

    private List<Role> roles;

}

同理:entity/Role

import lombok.Data;

import java.util.List;

@Data

public class Role {

    private String id;

    private String name;

    private List<User> users;

}

持久层:mapper/RoleMapper

import com.example.demo.entity.Role;

import org.apache.ibatis.annotations.Mapper;

import java.util.List;

@Mapper

public interface RoleMapper {

    List<Role> getAllUser();

}

mapper/UserMapper

import com.example.demo.entity.User;

import org.apache.ibatis.annotations.Mapper;

import java.util.List;

@Mapper

public interface UserMapper {

    List<User> getAllRole();

}

映射文件:mapper/RoleMapper

<resultMap id="roleMap" type="com.example.demo.entity.Role">

        <id property="id" column="id" jdbcType="VARCHAR"/>

        <result property="name" column="name" jdbcType="VARCHAR"/>

        <collection property="users" ofType="com.example.demo.entity.User">

            <result property="id" column="role_id" jdbcType="VARCHAR"/>

            <result property="name" column="name" jdbcType="VARCHAR"/>

        </collection>

    </resultMap>

    <select id="getAllUser" resultMap="roleMap">

        SELECT u.id,u.name,r.id AS role_id,r.name

        FROM user u

        LEFT OUTER JOIN user_role ur ON u.id = ur.user_id

        LEFT OUTER JOIN role r ON r.id = ur.role_id

    </select>

mapper/UserMapper

<resultMap id="userMap" type="com.example.demo.entity.User">

        <id property="id" column="id" jdbcType="VARCHAR"/>

        <result property="name" column="name" jdbcType="VARCHAR"/>

        <collection property="roles" ofType="com.example.demo.entity.Role">

            <result property="id" column="role_id" jdbcType="VARCHAR"/>

            <result property="name" column="name" jdbcType="VARCHAR"/>

        </collection>

    </resultMap>

    <select id="getAllRole" resultMap="userMap">

        SELECT u.id,u.name,r.id AS role_id,r.name

        FROM user u

        LEFT OUTER JOIN user_role ur ON u.id = ur.user_id

        LEFT OUTER JOIN role r ON r.id = ur.role_id

    </select>

测试:

@Autowired

    RoleMapper roleMapper;

    @Autowired

    UserMapper userMapper;

    @Test

    public void toGetAllUser(){

        List<Role> allUser = roleMapper.getAllUser();

        allUser.forEach(System.out::println);

/*

        Role(id=1001, name=ahzoo, users=[User(id=3001, name=ahzoo, roles=null), User(id=3002, name=ahzoo, roles=null)])

        Role(id=1002, name=ouo, users=[User(id=null, name=ouo, roles=null)])

*/

    }

    @Test

    public void toGetAllRole(){

        List<User> allRole = userMapper.getAllRole();

        allRole.forEach(System.out::println);

/*

        User(id=1001, name=ahzoo, roles=[Role(id=3001, name=ahzoo, users=null), Role(id=3002, name=ahzoo, users=null)])

        User(id=1002, name=ouo, roles=[Role(id=null, name=ouo, users=null)])

*/

    }


原文链接:https://juejin.cn/post/7120591216349020167

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,271评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,275评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,151评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,550评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,553评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,559评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,924评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,580评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,826评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,578评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,661评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,363评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,940评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,926评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,872评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,391评论 2 342

推荐阅读更多精彩内容