快速了解MyBatis---映射关系多对一

简介: 快速了解MyBatis---映射关系多对一

48e952f7f60d482c0d2854c834657a69.png映射关系多对一


映射关系-官方文档


文档地址: https://mybatis.org/mybatis-3/zh/sqlmap-xml.html


映射关系多对1-基本介绍


基本介绍


  1. 项目中多对1 的关系是一个基本的映射关系, 多对1, 也可以理解成是1 对多.
  2. User — Pet: 一个用户可以养多只宠物
  3. Dep —Emp : 一个部门可以有多个员工


注意细节


我们直接讲双向的多对一的关系,单向的多对一比双向的多对一简单。

在实际的项目开发中, 要求会使用双向的多对一的映射关系

什么是双向的多对一的关系: 比如通过User 可以查询到对应的Pet, 反过来,通过Pet 也可以级联查询到对应的User 信息.

多对多的关系,是在多对1 的基础上扩展.


映射关系多对1-映射方式


映射方式


方式1:通过配置XxxMapper.xml 实现多对1

方式2:通过注解的方式实现多对1


配置Mapper.xml 方式-应用实例


需求说明: 实现级联查询,通过user 的id 可以查询到用户信息,并可以查询到关联的pet信息,

反过来,通过Pet 的id 可以查询到Pet 的信息,并且可以级联查询到它的主人User对象信息。


  1. 创建mybatis_user 和mybatis_pet 表
CREATE TABLE mybatis_user
(
        id INT PRIMARY KEY AUTO_INCREMENT,
  NAME VARCHAR(32) NOT NULL DEFAULT ''
)CHARSET=utf8 ;
CREATE TABLE mybatis_pet
(
        id INT PRIMARY KEY AUTO_INCREMENT,
        nickname VARCHAR(32) NOT NULL DEFAULT '',
        user_id INT ,
        FOREIGN KEY (user_id) REFERENCES mybatis_user(id)
)CHARSET=utf8 ;
INSERT INTO mybatis_user
VALUES(NULL,'宋江'),(NULL,'张飞');
INSERT INTO mybatis_pet
VALUES(1,'黑背',1),(2,'小哈',1);
INSERT INTO mybatis_pet
VALUES(3,'波斯猫',2),(4,'贵妃猫',2);
SELECT * FROM mybatis_user;
SELECT * FROM mybatis_pet;


48e952f7f60d482c0d2854c834657a69.png

775ae87e9ec94d7785331995f585b0b0.png

  1. 创建src\main\java\com\nlc\entity\Pet.java
public class Pet {
    private Integer id;
    private String nickname;
    //一个pet对应一个主人 User对象
    private User user;
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getNickname() {
        return nickname;
    }
    public void setNickname(String nickname) {
        this.nickname = nickname;
    }
    public User getUser() {
        return user;
    }
    public void setUser(User user) {
        this.user = user;
    }
}


创建src\main\java\com\nlc\entity\User.java

public class User {
    private Integer id;
    private String name;
    //因为一个user可以养多个宠物,mybatis 使用集合List<Pet>体现这个关系
    private List<Pet> pets;
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public List<Pet> getPets() {
        return pets;
    }
    public void setPets(List<Pet> pets) {
        this.pets = pets;
    }
    //这toString会带来麻烦=>会造成StackOverFlow
    //@Override
    //public String toString() {
    //    return "User{" +
    //            "id=" + id +
    //            ", name='" + name + '\'' +
    //            ", pets=" + pets +
    //            '}';
    //}
}


创建PetMapper.java

public interface PetMapper {
    //通过User的id来获取pet对象,可能有多个,因此使用List接收
    public List<Pet> getPetByUserId(Integer userId);
    //通过pet的id获取Pet对象, 同时会查询到pet对象关联的user对象
    public Pet getPetById(Integer id);
}


  1. 创建UserMapper.java
public interface UserMapper {
    //通过id获取User对象
    public User getUserById(Integer id);
}


创建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 nameNlcace="com.nlc.mapper.UserMapper">
    <!--解读
    1、一定要想一想我们前面1-1是如何实现
    2、配置/实现 public User getUserById(Integer id);
    3、思路(1) 先通过user-id 查询得到user信息 (2) 再根据user-id查询对应的pet信息
      并映射到User-List<Pet> pets
    -->
    <resultMap id="UserResultMap" type="User">
        <id property="id" column="id"/>
        <result property="name" column="name"/>
        <!--解读:因为pets属性是集合,因此这里需要是collection标签来处理
        1. ofType="Pet" 指定返回的集合中存放的数据类型Pet
        2. collection 表示 pets 是一个集合
        3. property="pets" 是返回的user对象的属性 pets
        4. column="id" SELECT * FROM `mybatis_user` WHERE `id` = #{id} 返回的id字段对应的值
        -->
        <collection property="pets" column="id" ofType="Pet"
                    select="com.nlc.mapper.PetMapper.getPetByUserId"/>
    </resultMap>
    <select id="getUserById" parameterType="Integer" resultMap="UserResultMap">
        SELECT * FROM `mybatis_user` WHERE `id` = #{id}
    </select>
</mapper>


  1. 创建PetMapper.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 nameNlcace="com.nlc.mapper.PetMapper">
    <!--
        1、通过User的id来获取pet对象,可能有多个,因此使用List接收
        2、public List<Pet> getPetByUserId(Integer userId);
        3. 完成的思路和前面大体相同.
    -->
    <resultMap id="PetResultMap" type="Pet">
        <id property="id" column="id"/>
        <result property="nickname" column="nickname"/>
        <association property="user" column="user_id"
                     select="com.nlc.mapper.UserMapper.getUserById" />
    </resultMap>
    <select id="getPetByUserId" parameterType="Integer" resultMap="PetResultMap">
        SELECT * FROM `mybatis_pet` WHERE `user_id` = #{userId}
    </select>
    <!--说明
        1. 注意体会resultMap带来好处, 直接复用
        2. 实现/配置public Pet getPetById(Integer id);
        3. 通过pet的id获取Pet对象
    -->
    <select id="getPetById"  parameterType="Integer"  resultMap="PetResultMap">
        SELECT * FROM `mybatis_pet` WHERE `id` = #{id}
    </select>
</mapper>


创建PetMapperTest.java 完成测试

public class PetMapperTest {
    //属性
    private SqlSession sqlSession;
    private PetMapper petMapper;
    //初始化
    @Before
    public void init() {
        //获取到sqlSession
        sqlSession = MyBatisUtils.getSqlSession();
        petMapper = sqlSession.getMapper(PetMapper.class);
    }
    @Test
    public void getPetByUserId() {
        List<Pet> pets = petMapper.getPetByUserId(2);
        for (Pet pet : pets) {
            System.out.println("pet信息-" + pet.getId() + "-" + pet.getNickname());
            User user = pet.getUser();
            System.out.println("user信息 name-" + user.getName());
        }
        if(sqlSession != null) {
            sqlSession.close();
        }
    }
    @Test
    public void getPetById() {
        Pet pet = petMapper.getPetById(2);
        System.out.println("pet信息-" + pet.getId() + "-" + pet.getNickname());
        User user = pet.getUser();
        System.out.println("user信息-" + user.getId() + "-" + user.getName());
        if(sqlSession != null) {
            sqlSession.close();
        }
    }
}


创建UserMapperTest.java 完成测试

public class UserMapperTest {
    //属性
    private SqlSession sqlSession;
    private UserMapper userMapper;
    //初始化
    @Before
    public void init() {
        //获取到sqlSession
        sqlSession = MyBatisUtils.getSqlSession();
        userMapper = sqlSession.getMapper(UserMapper.class);
    }
    @Test
    public void getUserById() {
        User user = userMapper.getUserById(2);
        System.out.println("user信息-" + user.getId() + "-" + user.getName());
        List<Pet> pets = user.getPets();
        for (Pet pet : pets) {
            System.out.println("养的宠物信息-" + pet.getId() + "-" + pet.getNickname());
        }
        if(sqlSession != null) {
            sqlSession.close();
        }
    }
}


注解实现多对1 映射-应用实例


需求说明: 通过注解的方式来实现下面的多对1 的映射关系,实现级联查询,

完成前面完成的任务,通过User–>Pet 也可Pet->User , 在实际开发中推荐使用配置方式来做


  1. 创建UserMapperAnnotation.java
// UserMapperAnnotation:以注解的方式来配置多对一
public interface UserMapperAnnotation {
    //通过id获取User对象
    /**
     * 1. 注解的配置就是对应的Mapper.xml文件配置的,改写
     * 2.
     *     1、一定要想一想我们前面1-1是如何实现
     *     2、配置/实现 public User getUserById(Integer id);
     *     3、思路(1) 先通过user-id 查询得到user信息 (2) 再根据user-id查询对应的pet信息
     *       并映射到User-List<Pet> pets
     *     <resultMap id="UserResultMap" type="User">
     *         <id property="id" column="id"/>
     *         <result property="name" column="name"/>
     *         1. ofType="Pet" 指定返回的集合中存放的数据类型Pet
     *         2. collection 表示 pets 是一个集合
     *         3. property="pets" 是返回的user对象的属性 pets
     *         4. column="id" SELECT * FROM `mybatis_user` WHERE `id` = #{id} 返回的id字段对应的值
     *         <collection property="pets" column="id" ofType="Pet"
     *                     select="com.nlc.mapper.PetMapper.getPetByUserId"/>
     *     </resultMap>
     *     <select id="getUserById" parameterType="Integer" resultMap="UserResultMap">
     *         SELECT * FROM `mybatis_user` WHERE `id` = #{id}
     *     </select>
     */
    @Select("SELECT * FROM `mybatis_user` WHERE `id` = #{id}")
    @Results({
          @Result(id = true, property = "id", column = "id"),
          @Result(property = "name", column = "name"),
          //这里注意,pets属性对应的是集合
          @Result(property = "pets",
                        column = "id",
                        many = @Many(select = "com.nlc.mapper.PetMapperAnnotation.getPetByUserId"))
    })
    public User getUserById(Integer id);
}


  1. 创建PetMapperAnnotation.java
public interface PetMapperAnnotation {
    //通过User的id来获取pet对象,可能有多个,因此使用List接收
    /**
     * 1、通过User的id来获取pet对象,可能有多个,因此使用List接收
     * 2、public List<Pet> getPetByUserId(Integer userId);
     * 3. 完成的思路和前面大体相同.
     * <resultMap id="PetResultMap" type="Pet">
     * <id property="id" column="id"/>
     * <result property="nickname" column="nickname"/>
     * <association property="user" column="user_id"
     * select="com.nlc.mapper.UserMapper.getUserById" />
     * </resultMap>
     * <select id="getPetByUserId" parameterType="Integer" resultMap="PetResultMap">
     * SELECT * FROM `mybatis_pet` WHERE `user_id` = #{userId}
     * </select>
     */
    //id = "PetResultMap" 就是给我们的Results[Result Map] 指定一个名字
    //目的是为了后面复用
    @Select("SELECT * FROM `mybatis_pet` WHERE `user_id` = #{userId}")
    @Results(id = "PetResultMap", value = {
            @Result(id = true, property = "id", column = "id"),
            @Result(property = "nickname", column = "nickname"),
            @Result(property = "user",
                    column = "user_id",
                    one = @One(select = "com.nlc.mapper.UserMapperAnnotation.getUserById"))
    })
    public List<Pet> getPetByUserId(Integer userId);
    //通过pet的id获取Pet对象, 同时会查询到pet对象关联的user对象
    /**
     * <select id="getPetById"  parameterType="Integer"  resultMap="PetResultMap">
     * SELECT * FROM `mybatis_pet` WHERE `id` = #{id}
     * </select>
     * @ResultMap("PetResultMap") 使用/引用我们上面定义的 Results[ResultMap]
     */
    @Select("SELECT * FROM `mybatis_pet` WHERE `id` = #{id}")
    @ResultMap("PetResultMap")
    public Pet getPetById(Integer id);
}


  1. 创建UserMapperAnnotationTest.java 完成测试
public class UserMapperAnnotationTest {
    //属性
    private SqlSession sqlSession;
    private UserMapperAnnotation userMapperAnnotation;
    //初始化
    @Before
    public void init() {
        //获取到sqlSession
        sqlSession = MyBatisUtils.getSqlSession();
        userMapperAnnotation = sqlSession.getMapper(UserMapperAnnotation.class);
    }
    @Test
    public void getUserById() {
        User user = userMapperAnnotation.getUserById(2);
        System.out.println("user信息-" + user.getId() + "-" + user.getName());
        List<Pet> pets = user.getPets();
        for (Pet pet : pets) {
            System.out.println("宠物信息-" + pet.getId() + "-" + pet.getNickname());
        }
        if(sqlSession != null) {
            sqlSession.close();
        }
    }
}


  1. 创建PetMapperAnnotationTest.java 完成测试
public class PetMapperAnnotationTest {
    //属性
    private SqlSession sqlSession;
    private PetMapperAnnotation petMapperAnnotation;
    //初始化
    @Before
    public void init() {
        //获取到sqlSession
        sqlSession = MyBatisUtils.getSqlSession();
        petMapperAnnotation = sqlSession.getMapper(PetMapperAnnotation.class);
    }
    @Test
    public void getPetByUserId() {
        List<Pet> pets = petMapperAnnotation.getPetByUserId(1);
        for (Pet pet : pets) {
            System.out.println("宠物信息-" + pet.getId() + "-" + pet.getNickname());
        }
        if(sqlSession != null) {
            sqlSession.close();
        }
    }
    @Test
    public void getPetById() {
        Pet pet = petMapperAnnotation.getPetById(1);
        System.out.println("pet信息-" + pet.getId() + "-" +pet.getNickname());
        User user = pet.getUser();
        System.out.println("user信息-" + user.getId() + "-" + user.getName());
        if(sqlSession != null) {
            sqlSession.close();
        }
    }
}


相关文章
|
16天前
|
SQL 缓存 Java
【详细实用のMyBatis教程】获取参数值和结果的各种情况、自定义映射、动态SQL、多级缓存、逆向工程、分页插件
本文详细介绍了MyBatis的各种常见用法MyBatis多级缓存、逆向工程、分页插件 包括获取参数值和结果的各种情况、自定义映射resultMap、动态SQL
【详细实用のMyBatis教程】获取参数值和结果的各种情况、自定义映射、动态SQL、多级缓存、逆向工程、分页插件
|
2月前
|
SQL XML Java
mybatis复习04高级查询 一对多,多对一的映射处理,collection和association标签的使用
文章介绍了MyBatis中高级查询的一对多和多对一映射处理,包括创建数据库表、抽象对应的实体类、使用resultMap中的association和collection标签进行映射处理,以及如何实现级联查询和分步查询。此外,还补充了延迟加载的设置和用法。
mybatis复习04高级查询 一对多,多对一的映射处理,collection和association标签的使用
|
3月前
|
Java 数据库连接 mybatis
后端框架的学习----mybatis框架(9、多对一处理和一对多处理)
这篇文章介绍了在MyBatis框架中如何处理多对一和一对多的关联查询,通过定义`<resultMap>`和使用`<association>`与`<collection>`元素来实现对象间的关联映射。
|
4月前
|
SQL Java 数据库连接
idea中配置mybatis 映射文件模版及 mybatis plus 自定义sql
idea中配置mybatis 映射文件模版及 mybatis plus 自定义sql
91 3
|
4月前
|
Java 数据库连接 mybatis
mybatis映射关系(1-1 1-n n-n)
Mybatis 中的关系映射包括一对一、一对多和多对多。一对一映射可以通过ResultMap定义属性与字段的对应。一对多示例中,User类包含List&lt;Role&gt;,在User的mapper.xml中使用&lt;collection&gt;标签。多对一的情况,如Author与Blog,Blog的ResultMap中使用&lt;association&gt;来映射Author属性。多对多时,如部门与用户,通常需要中间表,并在双方实体中通过&lt;collection&gt;引用中间类,如UserForDept,来维护关系。
|
5月前
|
SQL XML Java
后端数据库开发JDBC编程Mybatis之用基于XML文件的方式映射SQL语句实操
后端数据库开发JDBC编程Mybatis之用基于XML文件的方式映射SQL语句实操
72 3
若依修改,集成mybatisplus报错,若依集成mybatisplus,总是找不到映射是怎么回事只要是用mp的方法就找报,改成mybatisPlus配置一定要改
若依修改,集成mybatisplus报错,若依集成mybatisplus,总是找不到映射是怎么回事只要是用mp的方法就找报,改成mybatisPlus配置一定要改
|
6月前
|
SQL Java 数据库连接
【Mybatis】深入学习MyBatis:概述、主要特性以及配置与映射
【Mybatis】深入学习MyBatis:概述、主要特性以及配置与映射
【Mybatis】深入学习MyBatis:概述、主要特性以及配置与映射
|
6月前
|
算法 BI 数据库
MyBatisPlus查询条件设置、映射匹配兼容性、id生成策略、多数据操作
MyBatisPlus查询条件设置、映射匹配兼容性、id生成策略、多数据操作
377 3
|
6月前
|
SQL Java 数据库连接
15:MyBatis对象关系与映射结构-Java Spring
15:MyBatis对象关系与映射结构-Java Spring
109 4