百木园-与人分享,
就是让自己快乐。

day08-MyBatis的关联映射02

MyBatis的关联映射02

3.一对多

3.1基本介绍

mybatis – MyBatis 3 | XML 映射器

多对一关系也是一个基本的映射关系,多对一,也可以理解为一对多。例如:

User--Pet:一个用户可以有多只宠物

Dep--Emp:一个部门有多个员工

双向的多对一关系:通过User可以查询到对应的所有Pet,反之,通过Pet也可以级联查询到对应的User信息。

多对多的关系就是在多对一的关系上拓展

3.2案例实现

映射方式:

方式1:通过配置映射文件实现多对一

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

需求说明:实现级联查询,通过user的user_id可以查询到User信息和关联的所有pet信息,反之,通过pet的pet_id也可以查询到Pet信息和user的信息

先创建user表和pet表:

-- 创建user表
CREATE TABLE `user`(
`id` INT PRIMARY KEY AUTO_INCREMENT,
`name` VARCHAR(32) NOT NULL DEFAULT \'\'
)CHARSET=utf8
DESC `user`;

-- 创建pet表
CREATE TABLE `pet`(
`id` INT PRIMARY KEY AUTO_INCREMENT,
`nickname` VARCHAR(32) NOT NULL DEFAULT \'\',
`user_id` INT,
FOREIGN KEY (user_id) REFERENCES `user`(id)
)CHARSET=utf8

image-20230301195756786

3.2.1方式一:配置方式

(1)User和Pet实体类

package com.li.entity;

/**
 * @author 李
 * @version 1.0
 */
public class User {
    private Integer id;
    private String name;
    //因为一个User可以养多个宠物,mybatis使用集合体现这个关系
    private List<Pet> pets;
    
    //setter、getter方法省略
    //双向映射不要使用toString方法,否则会造成栈溢出错误
}
package com.li.entity;

/**
 * @author 李
 * @version 1.0
 */
public class Pet {
    private Integer id;
    private String nickname;
    //一个pet对应一个user对象
    private User user;
    
	//setter、getter方法省略
    //双向映射不要使用toString方法,否则会造成栈溢出错误
}

(2)UserMapper接口和PetMapper接口

public interface UserMapper {
    //通过id获取User对象
    public User getUserById(Integer id);
}
public interface PetMapper {
    //通过user的id获取pet对象,可能有多个因此使用集合接收
    public List<Pet> getPetByUserId(Integer userId);
}

(3)UserMapper.xml,思路:

1)先通过user_id查询得到user信息

2)再根据user_id,查询对应的pet信息,并映射到user-List< Per> pets

多对多的映射思路和一对一的实现类似,不同的使用使用resultMap映射属性时使用的是collecting标签。

<mapper namespace=\"com.li.mapper.UserMapper\">
    <!--通过id获取User对象
        public User getUserById(Integer id);-->
    <select id=\"getUserById\" parameterType=\"Integer\" resultMap=\"resultUserMap\">
        SELECT * FROM `user` WHERE id = #{id};
    </select>

    <!--User的属性映射-->
    <resultMap id=\"resultUserMap\" type=\"User\">
        <id property=\"id\" column=\"id\"/>
        <result property=\"name\" column=\"name\"/>
        <!--1.因为pets属性是一个集合,因此要使用collection标签
            2.column=\"id\"的id是SELECT * FROM `user` WHERE id=#{id} 返回的字段
            3.ofType=\"Pet\"指定返回的集合存放的数据类型-->
        <collection property=\"pets\" column=\"id\" ofType=\"Pet\"
                    select=\"com.li.mapper.PetMapper.getPetByUserId\"/>
    </resultMap>
</mapper>

(4)PetMapper.xml,思路和前面大体相同

<mapper namespace=\"com.li.mapper.PetMapper\">
    <!--通过user的id获取pet对象,可能有多个因此使用集合接收
        public List<Pet> getPetByUserId(Integer userId);-->
    <select id=\"getPetByUserId\" parameterType=\"Integer\" resultMap=\"resultPetMap\">
        SELECT * FROM `pet` WHERE user_id =#{userId};
    </select>

    <resultMap id=\"resultPetMap\" type=\"Pet\">
        <id property=\"id\" column=\"id\"/>
        <result property=\"nickname\" column=\"nickname\"/>
        <association property=\"user\" column=\"user_id\"
                     select=\"com.li.mapper.UserMapper.getUserById\"/>
    </resultMap>
</mapper>

(5)测试getUserById()方法,通过UserId查找user对象和联系的pet信息

@Test
public void getUserById() {
    User user = userMapper.getUserById(2);
    System.out.println(\"user信息=\" + user.getId() + \"-\" + user.getName());
    for (Pet pet : user.getPets()) {
        System.out.println(\"宠物信息=\" + pet.getId() + \"-\" + pet.getNickname());
    }
    if (sqlSession != null) {
        sqlSession.close();
    }
}

测试结果:

image-20230301205442816

(6)测试getPetByUserId()方法,通过user的id获取pet对象

@Test
public void getPetByUserId() {
    List<Pet> pets = petMapper.getPetByUserId(1);
    for (Pet pet : pets) {
        System.out.println(\"UserId=\" + pet.getUser().getId()
                + \"-PetId=\" + pet.getId()
                + \"-PetNickName=\" + pet.getNickname());
    }
    if (sqlSession != null) {
        sqlSession.close();
    }
}

测试结果:

image-20230301205827599

resultMap可以复用,如果有其他方法是返回的和resultMap一样的类型,可以在实现该方法时引用该resultMap。

比如PetMapper接口中新声明了一个方法:

//通过pet的id获取Pet对象,同时查询到pet对象关联的user对象
public Pet getPetById(Integer id);

PerMapper.xml文件:

<!--这里可以直接复用之前的resultPetMap-->
<select id=\"getPetById\" parameterType=\"Integer\" resultMap=\"resultPetMap\">
    SELECT * FROM `pet` where id =#{id};
</select>

3.2.2方式二:注解方式

需求说明:通过注解的方式,实现双向的级联查询。

在实际开发中推荐使用配置的方式来做

(1)User和Pet实体类不变

(2)直接在接口中,通过注解实现级联查询

UserMapperAnnotation.java

package com.li.mapper;

import com.li.entity.User;
import org.apache.ibatis.annotations.*;

/**
 * @author 李
 * @version 1.0
 * 以注解的方式来实现多对一
 */
public interface UserMapperAnnotation {
    //通过id获取User对象
    @Select(value = \"SELECT * FROM `user` WHERE id = #{id}\")
    @Results({
            @Result(id = true, property = \"id\", column = \"id\"),
            @Result(property = \"name\", column = \"name\"),
            //这里对应返回List类型属性pets,使用注解的many属性
            @Result(property = \"pets\", column = \"id\",
                    many = @Many(select = 
                                 \"com.li.mapper.PetMapperAnnotation.getPetByUserId\"))
    })
    public User getUserById(Integer id);
}

PetMapperAnnotation.java

package com.li.mapper;

import com.li.entity.Pet;
import org.apache.ibatis.annotations.*;

import java.util.List;

/**
 * @author 李
 * @version 1.0
 */
public interface PetMapperAnnotation {
    //通过user的id获取pet对象
    @Select(value = \"SELECT * FROM `pet` WHERE user_id =#{userId}\")
    //配置了id之后就可以复用PetResuleMap
    @Results(id = \"PetResuleMap\", value = {
            @Result(id = true, property = \"id\", column = \"id\"),
            @Result(property = \"nickname\", column = \"nickname\"),
            @Result(property = \"user\", column = \"user_id\",
                    one = @One(select = 
                               \"com.li.mapper.UserMapperAnnotation.getUserById\"))
    })
    public List<Pet> getPetByUserId(Integer userId);

    
    //通过pet的id获取pet信息
    @Select(value = \" SELECT * FROM `pet` where id =#{id}\")
    @ResultMap(\"PetResuleMap\")//复用上面的PetResuleMap
    public Pet getPetById(Integer id);
}

3.3练习

自己设计dept(部门)和emp(雇员)表,它们是一对多的关系。

  1. 通过查询dept,可以级联查询到所有的emp信息
  2. 通过查询emp,也可以级联查询到对应的dept信息
  3. 拓展思考:多对多关系

来源:https://www.cnblogs.com/liyuelian/p/17170026.html
本站部分图文来源于网络,如有侵权请联系删除。

未经允许不得转载:百木园 » day08-MyBatis的关联映射02

相关推荐

  • 暂无文章