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

映射关系多对一

映射关系-官方文档

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

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

基本介绍

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

注意细节

  1. 我们直接讲双向的多对一的关系,单向的多对一比双向的多对一简单。
  2. 在实际的项目开发中, 要求会使用双向的多对一的映射关系
  3. 什么是双向的多对一的关系: 比如通过User 可以查询到对应的Pet, 反过来,通过Pet 也可以级联查询到对应的User 信息.
  4. 多对多的关系,是在多对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;

image-20230731145051413

  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 +
    //            '}';
    //}
}
  1. 创建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);
    }
    

    创建UserMapper.java

public interface UserMapper {

    //通过id获取User对象
    public User getUserById(Integer id);

}
  1. 创建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>
    
  2. 创建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>
  1. 创建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();
            }
        }
    }
    
  2. 创建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();
        }
    }
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

晨犀

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值