MyBatis--映射关系一对一和MyBatis--映射关系多对一 -都有基于xml和注解的教程

news2024/11/30 8:47:23

目录

MyBatis--映射关系一对一

映射关系-官方文档

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

注意细节

映射方式

方式1

创建idencardv 表

创建person表

创建新的 module(mybatis-mapping), 相关配置文件可以从上一个 module 拷贝

创建IdenCard.java对应表类  

创建Person.java对应表类  

创建IdenCardMapper接口

创建IdenCardMapper.xml

创建 PersonMapper接口

创建PersonMapper.xml

创建IdenCardMapperTest .java , 完成测试

创建PersonMapperTest.java , 完成测试

方式2

第 2 种映射方式,完成 1 对 1 映射关系

修改 PersonMapper.java接口

修改PersonMapper.xml

修改 PersonMapperTest.java 完成测试

 根据id获取到身份证序列号, 并查询级联的

修改IdenCardMapper.java接口

修改IdenCardMapper.xml

修改IdenCardMapperTest.java

注解的方式实现-应用实例

创建IdenCardMapperAnnotaion.java

创建PersonMapperAnn otation.java

 创建PersonMapperAnno tationTest.java 完成测试

创建IdenCardMapperAnnotationTest

注意事项和细节

MyBatis--映射关系多对一 

映射关系-官方文档

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

注意细节

映射方式

需求说明:

创建 mybatis_user 表

创建mybatis_pet 表

添加的数据

创建 对应的entiey对象User类

创建 对应的entiey对象Pet类

创建PetMapper.java接口

创建UserMapper.java接口

创建 UserMapper.xml

创建 PetMapper.xml 

创建 UserMapperTest.java 完成测试

创建 PetMapperTest.java 完成测试

 注解实现多对1 映射

 创建 PetMapperAnnotation.java

 创建 UserMapperAnnotation.java

创建 PetMapperAnnotationTest.java 完成测试

创建 UserMapperAnnotationTest.java 完成测试


MyBatis--映射关系一对一

映射关系-官方文档

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

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

1.     项目中1 对1 的关系是一个基本的映射关系,比如:Person(人) --- IDCard(身份证)

2.     我们看看再MyBatis 中如何实现1 对1 的处理

注意细节

1 对1 ,我们这里就研究一下单向1 对1 即可以

映射方式

1.     通过配置XxxMapper.xml 实现1 对1 [配置方式]

2.     通过注解的方式实现 1 对 1 [注解方式]

方式1

通过配置XxxMapper.xml 的方式来实现下面的1 对1 的映射关系

实现级联查询,通过person 可以获取到对应的idencard 信息

创建idencardv 表

CREATE TABLE idencard
(
id INT PRIMARY KEY AUTO_INCREMENT,
card_sn VARCHAR(32) NOT NULL DEFAULT ''
)CHARSET utf8 ;

创建person表

CREATE TABLE person
(
id INT PRIMARY KEY AUTO_INCREMENT, NAME VARCHAR(32) NOT NULL DEFAULT '', 
card_id INT ,
FOREIGN KEY (card_id) REFERENCES idencard(id) 
)CHARSET utf8;

创建新的 module(mybatis-mapping), 相关配置文件可以从上一个 module 拷贝

创建IdenCard.java对应表类  

package com.wyxedu.entity;


public class IdenCard {
    /**
     * CREATE TABLE idencard
     * (
     * id INT PRIMARY KEY AUTO_INCREMENT,
     * card_sn VARCHAR(32) NOT NULL DEFAULT ''
     * )CHARSET utf8 ;
     */
    private Integer id;
    private String card_sn;

    //通过查询IdenCard 可以级联查询得到person
    private Person person;

    public Person getPerson() {
        return person;
    }

    public void setPerson(Person person) {
        this.person = person;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getCard_sn() {
        return card_sn;
    }

    public void setCard_sn(String card_sn) {
        this.card_sn = card_sn;
    }

    @Override
    public String toString() {
        return "IdenCard{" +
                "id=" + id +
                ", card_sn='" + card_sn + '\'' +
                ", person=" + person +
                '}';
    }
}

创建Person.java对应表类  

package com.wyxedu.entity;

public class Person {

    /**
     * CREATE TABLE person
     * (
     * id INT PRIMARY KEY AUTO_INCREMENT,
     * NAME VARCHAR(32) NOT NULL DEFAULT '',
     * card_id INT ,
     * FOREIGN KEY (card_id) REFERENCES idencard(id)
     * )CHARSET utf8;
     */
    private Integer id;
    private String name;
    //因为我们的需要实现一个级联操作, 一个人需要对应一个身份证
    //这里需要直接定义IdenCard对象属性
    private IdenCard card;

    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 IdenCard getCard() {
        return card;
    }

    public void setCard(IdenCard card) {
        this.card = card;
    }

    @Override
    public String toString() {
        return "Person{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", card=" + card +
                '}';
    }
}

创建IdenCardMapper接口

public interface IdenCardMapper {
    //根据id获取到身份证序列号
    public IdenCard getIdenCardById(Integer id);
}

创建IdenCardMapper.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.wyxedu.mapper.IdenCardMapper">

    <!--
        1、配置/实现//根据id获取到身份证序列号
        2、public IdenCard getIdenCardById(Integer id);
    -->
    <select id="getIdenCardById" parameterType="Integer"
            resultType="IdenCard">
        SELECT * FROM `idencard` WHERE `id` = #{id}
    </select>
</mapper>

创建 PersonMapper接口

public interface PersonMapper {
    //通过Person的id获取到Person,包括这个Person关联的IdenCard对象[级联查询]
    public Person getPersonById(Integer id);

创建PersonMapper.xml

1、配置/实现public Person getPersonById(Integer id);

2、完成通过Person的id获取到Person,包括这个Person关联的IdenCard对象[级联查询].

3. 看到如果配置成简单 resultType="Person" 问题就是没有实现级联查询.

4. 自定义resultMap 搞定 映射返回的结果

5. 因为 getPersonById 最终返回的是 Person对象[只是有级联的对象属性], type仍然配置"Person" .

<?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.wyxedu.mapper.PersonMapper">
    <!--
        1、配置/实现public Person getPersonById(Integer id);
        2、完成通过Person的id获取到Person,包括这个Person关联的IdenCard对象[级联查询]
        3. 看到如果配置成简单 resultType="Person" 问题就是没有实现级联查询
        4. 自定义resultMap 搞定 映射返回的结果
        5. 因为 getPersonById 最终返回的是 Person对象[只是有级联的对象属性], type仍然配置"Person"
    -->
    <resultMap id="PersonResultMap" type="Person">
        <!--<result property="id" column="id"/>-->
        <!--id – 一个 ID 结果;标记出作为 ID 的结果可以帮助提高整体性能
            1.property="id" 表示person 属性 id ,通常是主键
            2.column="id" 表示对应表的字段
        -->

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

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

        <!--association – 一个复杂类型的关联
        1. property="card" 表示 Person对象的 card 属性
        2. javaType="IdenCard" 表示card 属性 的类型
        3. column="id" 是从我们的 下面这个语句查询后返回的字段
        SELECT *  FROM `person`,`idencard` WHERE `person`.id=1
        AND `person`.card_id = `idencard`.id

        -->
        <association property="card" javaType="IdenCard">
            <result property="id" column="id"/>
            <result property="card_sn" column="card_sn"/>
        </association>
    </resultMap>
    <select id="getPersonById" parameterType="Integer"
            resultMap="PersonResultMap">
        SELECT *  FROM `person`,`idencard` WHERE `person`.id = #{id}
        AND `person`.card_id = `idencard`.id
    </select>
</mapper>

创建IdenCardMapperTest .java , 完成测试

public class IdenCardMapperTest {

    //属性
    private SqlSession sqlSession;
    private IdenCardMapper idenCardMapper;

    //初始化
    @Before
    public void init() {
        //获取到sqlSession
        sqlSession = MyBatisUtils.getSqlSession();
        idenCardMapper = sqlSession.getMapper(IdenCardMapper.class);
    }

    @Test
    public void getIdenCardById() {
        IdenCard idenCard = idenCardMapper.getIdenCardById(1);
        System.out.println("idenCard--" + idenCard);
        if (sqlSession != null) {
            sqlSession.close();
        }
    }
}

创建PersonMapperTest.java , 完成测试

public class PersonMapperTest {

    //属性
    private SqlSession sqlSession;
    private PersonMapper personMapper;

    //初始化
    @Before
    public void init() {
        //获取到sqlSession
        sqlSession = MyBatisUtils.getSqlSession();
        personMapper = sqlSession.getMapper(PersonMapper.class);
    }

    @Test
    public void getPersonById() {
        Person person = personMapper.getPersonById(1);
        System.out.println("person--" + person);
        if (sqlSession != null) {
            sqlSession.close();
        }

    }

方式2

说明:通过配置XxxMapper.xml 的方式来实现下面的1 对1 的映射关系,

实现级联查询,通过person 可以获取到对应的identcard 信息使用.

第 2 种映射方式,完成 1 对 1 映射关系

修改 PersonMapper.java接口

public interface PersonMapper {
    //通过Person的id获取到Person,包括这个Person关联的IdenCard对象[级联查询]
    public Person getPersonById(Integer id);

    //通过Person的id获取到Person,包括这个Person关联的IdenCard对象,方式2
    public Person getPersonById2(Integer id);
}

修改PersonMapper.xml

    <resultMap id="PersonResultMap2" type="Person">
        <id property="id" column="id"/>
        <result property="name" column="name"/>
        <!--再次解读
        1. mybatis第二种方式核心思想: 将这个多表联查,分解成单表操作 , 这样简洁,而且易于维护 ,推荐
        2. 而且可以复用你已经写好的方法 -组合
        3. property="card": 表示 Person对象的 card 属性
        4. column="card_id" 这个是
        SELECT * FROM `person` WHERE `id` = #{id}  返回的 字段 card_id 信息/数据
        5. 返回的 字段 card_id 信息/数据 作为getIdenCardById入参, 来执行
        -->

        <association property="card" column="card_id"
                     select="com.wyxedu.mapper.IdenCardMapper.getIdenCardById" />
    </resultMap>
    <select id="getPersonById2" parameterType="Integer" resultMap="PersonResultMap2">
        SELECT * FROM `person` WHERE `id` = #{id}
    </select>
</mapper>

修改 PersonMapperTest.java 完成测试

 @Test
    public void getPersonById2() {
        Person person = personMapper.getPersonById2(1);
        System.out.println("person---------" + person);
        if (sqlSession != null) {
            sqlSession.close();
        }
    }

 根据id获取到身份证序列号, 并查询级联的

修改IdenCardMapper.java接口

public interface IdenCardMapper {
    //根据id获取到身份证序列号
    public IdenCard getIdenCardById(Integer id);

    //根据id获取到身份证序列号, 并查询级联的
    public IdenCard getIdenCardById2(Integer id);

}

修改IdenCardMapper.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.wyxedu.mapper.IdenCardMapper">

    <!--
        1、配置/实现//根据id获取到身份证序列号
        2、public IdenCard getIdenCardById(Integer id);
    -->
    <select id="getIdenCardBy   Id" parameterType="Integer"
            resultType="IdenCard">
        SELECT * FROM `idencard` WHERE `id` = #{id}
    </select>


    <!--
    1、根据id获取到身份证序列号, 并查询级联的person
    2、public IdenCard getIdenCardById2(Integer id);
    3. 自定义一个resultMap , 完成属性值映射
    -->
    <resultMap id="IdenCardResultMap" type="IdenCard">
        <id property="id" column="id"/>
        <id property="card_sn" column="card_sn"/>
        <!--写到这里
        1. 我们分析出来,需要根据 SELECT * FROM idencard WHERE id = #{id} , 返回的 id字段的值
        2. 作为入参,传递给 一个方法.getPersonByCardId , 通过这个方法,可以返回该idencard对应的person信息
        -->
        <association property="person" column="id"
                     select="com.wyxedu.mapper.PersonMapper.getPersonByCardId"/>
    </resultMap>
    <select id="getIdenCardById2" parameterType="Integer" resultMap="IdenCardResultMap" >
        SELECT * FROM idencard WHERE id = #{id}
    </select>
</mapper>

修改IdenCardMapperTest.java

    @Test
    public void getIdenCardById2() {
        IdenCard idenCard = idenCardMapper.getIdenCardById2(200);

        System.out.println("idenCard2--" + idenCard);
        if (sqlSession != null) {
            sqlSession.close();
        }
    }

注解的方式实现-应用实例

通过注解的方式来实现下面的1 对1 的映射关系,实现级联查询,通过person 可以获取到对应的identcard 信息.
 

说明: 在实际开发中还是推荐使用配置方式

创建IdenCardMapperAnnotaion.java

package com.wyxedu.mapper;

import com.wyxedu.entity.IdenCard;
import org.apache.ibatis.annotations.Select;

/**
 * IdenCardMapperAnnotation: 使用注解方式实现1对1的映射
 */
public interface IdenCardMapperAnnotation {
    //根据id获取到身份证
    //这个方法不需要返回任何级联对象
    @Select("SELECT * FROM `idencard` WHERE `id` = #{id}")
    public IdenCard getIdenCardById(Integer id);
}

创建PersonMapperAnnotation.java

import com.wyxedu.entity.Person;
import org.apache.ibatis.annotations.One;
import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.Results;
import org.apache.ibatis.annotations.Select;

public interface PersonMapperAnnotation {
    //这里注解实现方法
    //说明: 注解的形式就是对前面xml配置方式的体现
    //这里同学们可以结合前面讲解的xml配置时,加入的注释来理解

    @Select("SELECT * FROM `person` WHERE `id` = #{id}")
    @Results({
          @Result(id = true, property = "id", column = "id"),
          @Result(property = "name", column = "name"),
          @Result(property = "card", column = "card_id",
                  one = @One(select = "com.hspedu.mapper.IdenCardMapper.getIdenCardById"))
    })
    public Person getPersonById(Integer id);
}

 创建PersonMapperAnno tationTest.java 完成测试

package com.wyxedu.mapper;

import com.wyxedu.entity.Person;
import com.wyxedu.util.MyBatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Before;
import org.junit.Test;


public class PersonMapperAnnotationTest {

    //属性
    private SqlSession sqlSession;
    private PersonMapperAnnotation personMapperAnnotation;

    //初始化
    @Before
    public void init() {
        //获取到sqlSession
        sqlSession = MyBatisUtils.getSqlSession();
        personMapperAnnotation = sqlSession.getMapper(PersonMapperAnnotation.class);
    }

    @Test
    public void getPersonById() {

        Person person = personMapperAnnotation.getPersonById(1);
        System.out.println("person----" + person);
        if(sqlSession != null) {
            sqlSession.close();
        }

    }
}

创建IdenCardMapperAnnotationTest

public class IdenCardMapperAnnotationTest {

    //属性
    private SqlSession sqlSession;
    private IdenCardMapperAnnotation idenCardMapperAnnotation;

    //初始化
    @Before
    public void init() {
        //获取到sqlSession
        sqlSession = MyBatisUtils.getSqlSession();
        idenCardMapperAnnotation = sqlSession.getMapper(IdenCardMapperAnnotation.class);
    }

    @Test
    public void getIdenCardById() {

        IdenCard idenCard =
                idenCardMapperAnnotation.getIdenCardById(1);

        System.out.println("idenCard--注解--" + idenCard);

        if(sqlSession != null) {
            sqlSession.close();
        }

    }
}

注意事项和细节

1.    表是否设置外键, 对MyBatis 进行对象是否进行级联映射是没有任何影响的
2.    举例: 去掉 person 表的外键 , 我们进行测试, 依然可以获取相应的级联对象

 


 

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.     方式 2:通过注解的方式实现 多对 1

需求说明:

 实现级联查询,通过user 的id 可以查询到用户信息,并可以查询到关联的pet信息,反过来,通过 Pet 的 id 可以查询到 Pet 的信息,并且可以级联查询到它的主人User对象信息

创建 mybatis_user 表

CREATE TABLE mybatis_user
(id INT PRIMARY KEY AUTO_INCREMENT,
`name` VARCHAR(32) NOT NULL DEFAULT ''
)CHARSET=utf8 ;

创建mybatis_pet 表

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);

创建 对应的entiey对象User类

脑子要有印象 OOP. 

package com.wyxedu.entity;

import java.util.List;

public class User {

    /**
     * CREATE TABLE mybatis_user
     * (id INT PRIMARY KEY AUTO_INCREMENT,
     * NAME VARCHAR(32) NOT NULL DEFAULT ''
     * )CHARSET=utf8 ;
     */

    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 +
    //            '}';
    //}
}

创建 对应的entiey对象Pet类

package com.wyxedu.entity;


public class Pet {
    /**
     * 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 ;
     */
    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;
    }

    //@Override
    //public String toString() {
    //    return "Pet{" +
    //            "id=" + id +
    //            ", nickname='" + nickname + '\'' +
    //            ", user=" + user +
    //            '}';
    //}
}

创建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);

}

创建 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.wyxedu.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.wyxedu.mapper.PetMapper.getPetByUserId"/>
    </resultMap>
    <select id="getUserById" parameterType="Integer" resultMap="UserResultMap">
        SELECT * FROM `mybatis_user` WHERE `id` = #{id}
    </select>

</mapper>

创建 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 namespace="com.wyxedu.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.wyxedu.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>

创建 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();
        }
    }
}

创建 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();
        }
    }

}

 注解实现多对1 映射

 需求说明:

                通过注解的方式来实现下面的多对1 的映射关系,实现级联查询,完成前面完成的任务,通过User-->Pet 也可Pet->User , 在实际开发中推荐使用配置方式来做

 创建 PetMapperAnnotation.java

package com.wyxedu.mapper;

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

import java.util.List;

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.hspedu.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.hspedu.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);
}

 创建 UserMapperAnnotation.java

package com.wyxedu.mapper;

import com.wyxedu.entity.Pet;
import com.wyxedu.entity.User;
import com.wyxedu.util.MyBatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Before;
import org.junit.Test;

import java.util.List;
/**
 * 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.hspedu.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.hspedu.mapper.PetMapperAnnotation.getPetByUserId"))
    })
    public User getUserById(Integer id);
}

创建 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();
        }
    }
}

创建 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();
        }
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/512187.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Vue2相关面试题(持续更新)

前言 目前这套面试题只适合 初级前端&#xff0c;后面会进行深层次补充和拓展以及Vue2源代码的讲解&#xff08;虽然Vue2今年开始不维护了&#xff0c;但是我的面试题不会止步&#xff0c;冲冲冲&#xff09;。在面试的过程中&#xff0c;一定要清楚哪些该说哪些不该说&#x…

云剪辑-B端在线剪辑⼯具架构设计与演进

腾讯云音视频的云剪辑致力于让客户在自己的应用&#xff08;Web、小程序&#xff09;中快速集成剪辑能力&#xff0c;同时强大的模板能力能够极大地提升视频生产效率。我们在探索B端在线剪辑产品的过程中遇到不少挑战&#xff1a;如何满足快速与定制两种集成场景&#xff1f;如…

Linux性能监控

一、htop 安装&#xff1a;yum install htop -ytop是linux下常用的监控程序&#xff0c;htop相当于其加强版&#xff0c;颜色显示不同参数&#xff0c;且支持鼠标操作&#xff0c;相对于top简单和人性化&#xff01;第一行与第二行&#xff0c;显示CPU当前的运行负载&#xff…

F407标准库之时钟系统

主要参考正点原子数据手册和源码资料等。 第19讲 STM32时钟系统精讲_哔哩哔哩_bilibili 此处记录较为重要或者较易出错的一些遗漏之处&#xff0c;作为补充。 一般而言&#xff0c;时钟越高&#xff0c;速度越快&#xff0c;但同时抗干扰能力也越差&#xff0c;功耗也越高&am…

java入门学习

输入 数字输入&#xff08;为什么类型的数字就是sc.next类型&#xff09;float sumsc.nextFloat() int xsc.nextInt(); import java.util.Scanner;public class 相加问题 {public static void main(String[] args){Scanner scnew Scanner(System.in);int xsc.nextInt();int …

AMB300系列母线槽红外测温解决方案某锂电厂房项目案例分享

安科瑞 耿敏花 一、 行业背景 近年来&#xff0c;在国家政策引导与技术革新驱动的双重作用下&#xff0c;锂电产业保持快速增长态势&#xff0c;产业规模持续扩大&#xff0c;同时新能源产业工厂锂电池生产线对于电的依赖性很高&#xff0c;因而对供电设备的可靠性提出…

php+vue网上培训课程直播授课学习平台

运行环境:phpstudy/wamp/xammp等 开发语言&#xff1a;php 后端框架&#xff1a;Thinkphp5 前端框架&#xff1a;vue.js 服务器&#xff1a;apache 数据库&#xff1a;mysql 1、优智学在线授课平台主要是针对 疫情期间高校对在线教学直播的需求&#xff0c;为在校师生提供高质量…

TOGAF® 基本内容—架构开发方法—E阶段:机会和解决方案

本章描述识别有效交付的交付工具&#xff08;项目、项目群或项目组合&#xff09;的过程 在前面阶段确定的目标体系结构。 一、目标 E阶段的目标是&#xff1a; 根据差距分析和候选架构生成架构路线图的初始完整版本 阶段 B、C 和 D 的路线图组件确定是否需要增量方法&#xf…

WooCommerce电商开发:高性能订单存储HPOS性能基准测试

自去年以来&#xff0c;我们一直致力于构建和推出 HPOS&#xff08;高性能订单存储&#xff09;作为一项可选功能。这改变了我们在数据库中存储订单数据的方式&#xff0c;从自定义帖子类型 wp_post和wp_postmeta表到专门用于存储订单数据的自定义表。我们还发布了这些表的详细…

六、Spring Cloud Alibaba-nacos配置中心

一、Nacos配置中心 前面说了三、Spring Cloud Alibaba组件nacos&#xff0c;主要介绍的是服务发现。该篇主要介绍配置中心的功能。 官方地址&#xff1a; https://github.com/alibaba/spring-cloud-alibaba/wiki/Nacos-config。 Nacos 提供用于存储配置和其他元数据的 key/val…

tomcat集群下的session共享和负载均衡(memcache实现)

环境 操作系统&#xff1a;windows tomcat1&#xff1a;Apache Tomcat/7.0.52&#xff08;8085&#xff09; tomcat2&#xff1a;Apache Tomcat/7.0.52&#xff08;8086&#xff09; jdk&#xff1a;1.8.0_251 nginx&#xff1a;nginx-1.20.1&#xff08;8070&#xff09; memc…

美颜SDK的算法分析:探究其背后的机器学习模型

美颜SDK作为常见的美颜工具&#xff0c;其使用的算法也备受关注。本文将从机器学习的角度&#xff0c;深入分析美颜SDK的算法模型与实现原理。 一、算法模型 美颜SDK主要采用的算法模型是卷积神经网络&#xff08;Convolutional Neural Network&#xff0c;CNN&#xff09;。…

网卡名称排序

udev是一种动态设备管理系统&#xff0c;用于在Linux系统中自动管理设备的插拔、识别、配置等操作。它的主要作用是监视系统中的设备事件&#xff0c;并根据设备事件动态地创建、删除或修改系统中的设备节点。 udev的工作原理是通过读取系统中的硬件信息、驱动程序和设备特征信…

AI天后,在线飙歌,人工智能AI孙燕姿模型应用实践,复刻《遥远的歌》,原唱晴子(Python3.10)

忽如一夜春风来&#xff0c;亚洲天后孙燕姿独特而柔美的音色再度响彻华语乐坛&#xff0c;只不过这一次&#xff0c;不是因为她出了新专辑&#xff0c;而是人工智能AI技术对于孙燕姿音色的完美复刻&#xff0c;以大江灌浪之势对华语歌坛诸多经典作品进行了翻唱&#xff0c;还原…

李沐论文精度系列之九:InstructGPT

文章目录 一、背景1.1 时间线1.2 ChatGPT功能展示1.3 指示学习&#xff08;Instruct Learning&#xff09;和提示&#xff08;Prompt Learning&#xff09;学习1.4 人工反馈的强化学习&#xff08;RLHF&#xff09; 二、摘要三、导言3.1 算法3.2 结论 四、方法和实验细节4.1 数…

【数据结构与算法】树和二叉树

1 树 1.1 术语 关系术语 孩子结点 —— 子树的根 父结点 兄弟结点 —— 同一个结点的孩子结点互为兄弟 祖先结点 后代结点 层次类术语 根的层次为1 其余结点的层次为其父结点层次加1 高度/深度 —— 整个树中结点的最大层次 度 —— 结点的孩子数目称为结点的度 叶子&#xf…

Smartbi携手广州轻工集团打造集团价值创造型总部

广州轻工工贸集团有限公司&#xff08;简称“广州轻工集团”&#xff09;是广州市第一家工贸合一的大型企业集团公司&#xff0c;最早起源于1950年9月成立的广州市合作事业管理局&#xff0c;逐渐演化形成广州市轻工业局。1995年10月&#xff0c;广州市轻工业局成建制改建为经济…

spring-transaction源码分析(3)Transactional事务失效原因

问题概述 在Transactional方法中使用this方式调用另一个Transactional方法时&#xff0c;拦截器无法拦截到被调用方法&#xff0c;严重时会使事务失效。 类似以下代码&#xff1a; Transactional public void insertBlogList(List<Blog> blogList) {for (Blog blog : …

【人工智能】在VScode中使用AI插件Bito,功能与ChatGPT类似

文章目录 前言一、到官网下载VScode软件二、VScode软件安装步骤三、Bito插件下载与VScode软件中的使用四、注册Bito 前言 之前在VScode中使用ChatGPT中文版&#xff0c;后来要注册与收费&#xff0c;可采用一些ChatGPT中文版的替代插件。 后发现BitoAI插件功能同样强大&#…

港联证券|断臂、收缩、变阵 “中植系”何去何从?

经历灵魂人物猝然离世的巨震&#xff0c;国内最老牌资本系之一的“中植系”&#xff0c;尚未显露出穿越周期的企稳之象&#xff0c;似仍在风雨飘摇。 投资端&#xff0c;随着监管持续升级与注册制改革全面推进&#xff0c;“中植系”惯用“PE上市公司”以低买高卖的资本套利模式…