快速学会MyBatis映射关系一对一

简介: 快速学会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 对1-映射方式


映射方式


  1. 通过配置XxxMapper.xml 实现1 对1 [配置方式]
  2. 通过注解的方式实现1 对1 [注解方式]
  3. 我们用代码实现,应用举例


配置Mapper.xml 的方式


方式1

通过配置XxxMapper.xml 的方式来实现下面的1 对1 的映射关系,实现级联查询,通过person 可以获取到对应的idencard 信息。

完成功能示意(如下)

person--Person{id=1, name=' 张三', card=IdenCard{id=1,card_sn='111111111111110'}}


创建person 表和idencard 表

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;
-- 创建mybatis_idencard 表
CREATE TABLE idencard
(
    id INT PRIMARY KEY AUTO_INCREMENT,
    card_sn VARCHAR(32) NOT NULL DEFAULT ''
)CHARSET utf8 ;
 -- 添加数据
INSERT INTO idencard VALUES(1,'111111111111110');
INSERT INTO person VALUES(1,'张三',1);


创建新的module(mybatis-mapping), 相关配置文件可以从上一个module —自己实现MyBatis 底层机制–抽丝剥茧(上)拷贝。


创建com\nlc\entity\IdenCard.java

public class IdenCard {
    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 +
                '}';
    }
}


创建com\nlc\entity\Person.java

public class Person {
    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 +
                '}';
    }
}


创建com\nlc\mapper\IdenCardMapper.java

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


创建com\nlc\mapper\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.nlc.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.java

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


创建PersonMapper.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.nlc.mapper.PersonMapper">
    <!--
        1、配置/实现public Person getPersonById(Integer id);
        2、完成通过Person的id获取到Person,包括这个Person关联的IdenCard对象[级联查询]
        3. 先用大家容易想到的方式-分析问题-解决问题
        4. 看到如果配置成简单 resultType="Person" 问题就是没有实现级联查询
        5. 自定义resultMap 搞定 映射返回的结果
        6. 因为 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>


创建src\test\java\com\nlc\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();
        }
    }
}


创建src\test\java\com\nlc\mapper\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 信息。

完成功能示意结果(如下)

person--Person{id=1, name=' 张三', card=IdenCard{id=1,card_sn='111111111111110'}}


修改PersonMapper.java 和PersonMapper.xml 使用第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

 <!--
        1、通过Person的id获取到Person,包括这个Person关联的IdenCard对象,方式2
        2、public Person getPersonById2(Integer id);
        3. 这里的方式和前面不同.
        1) 先通过 SELECT * FROM `person` WHERE `id` = #{id} 返回 person信息
        2) 再通过 返回的card_id 值,再执行操作,得到IdenCard 数据
    -->
    <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.nlc.mapper.IdenCardMapper.getIdenCardById" />
    </resultMap>
    <select id="getPersonById2" parameterType="Integer" resultMap="PersonResultMap2">
        SELECT * FROM `person` WHERE `id` = #{id}
    </select>


修改PersonMapperTest.java 完成测试

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


注解的方式实现


应用实例

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

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

创建com\nlc\mapper\IdenCardMapperAnnotaion.java

public interface IdenCardMapperAnnotation {
    //根据id获取到身份证
    //这个方法不需要返回任何级联对象
    @Select("SELECT * FROM `idencard` WHERE `id` = #{id}")
    public IdenCard getIdenCardById(Integer id);
}


创建com\nlc\mapper\PersonMapperAnnotation.java

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",
                  //card不对应简单的column,是通过一个方法获取,
                  //card_id是通过以前的方法,返回的一个叫card_id的值,下面的方法是需要一个入参的
                  one = @One(select = "com.nlc.mapper.IdenCardMapper.getIdenCardById"))
        //因为是一对一的映射所以采用one = @One(***)的形式,可以debug看一下他的源码里面的属性
    })
    public Person getPersonById(Integer id);
}


创建com\nlc\mapper\PersonMapperAnnotationTest.java 完成测试

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


总结


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

727c2b0ab9974f32be40f48269e286a3.png

相关文章
|
3月前
|
SQL Java 数据库连接
MyBatis 的映射关系
MyBatis 核心功能之一是映射关系,支持一对一、一对多和多对多三种 ORM 映射。通过实体类与配置文件结合,开发者可灵活实现数据关联,提升数据库操作效率。
273 4
|
7月前
|
SQL XML Java
菜鸟之路Day35一一Mybatis之XML映射与动态SQL
本文介绍了MyBatis框架中XML映射与动态SQL的使用方法,作者通过实例详细解析了XML映射文件的配置规范,包括namespace、id和resultType的设置。文章还对比了注解与XML映射的优缺点,强调复杂SQL更适合XML方式。在动态SQL部分,重点讲解了`&lt;if&gt;`、`&lt;where&gt;`、`&lt;set&gt;`、`&lt;foreach&gt;`等标签的应用场景,如条件查询、动态更新和批量删除,并通过代码示例展示了其灵活性与实用性。最后,通过`&lt;sql&gt;`和`&lt;include&gt;`实现代码复用,优化维护效率。
634 5
|
9月前
|
SQL XML Java
七、MyBatis自定义映射resultMap
七、MyBatis自定义映射resultMap
260 6
|
9月前
|
Java 数据库连接 mybatis
MyBatis篇-映射关系(1-1 1-n n-n)
本文介绍了MyBatis中四种常见关系映射的配置方法,包括一对一、一对多、多对一和多对多。**一对一**通过`resultMap`实现属性与字段的映射;**一对多**以用户-角色为例,使用`&lt;collection&gt;`标签关联集合数据;**多对一**以作者-博客为例,利用`&lt;association&gt;`实现关联;**多对多**则通过引入第三方类(如UserForDept)分别在User和Dept类中添加集合属性,并配置对应的`&lt;collection&gt;`标签完成映射。这些方法解决了复杂数据关系的处理问题,提升了开发效率。
|
11月前
|
XML Java 数据库连接
Mybatis一对一,一对多关联查询
## MyBatis一对一、一对多关联查询详解 MyBatis是一款优秀的持久层框架,提供了灵活的SQL映射功能,支持复杂的数据库操作。本文将详细介绍MyBatis中一对一和一对多关联查询的实现。 ### 一对一关联查询 一对一关联关系指的是一个表中的一条记录与另一个表中的一条记录相关联。例如,一个用户有一个地址信息。 #### 数据库表设计 假设有两个表:`user`和 `address`。 ``` CREATE TABLE user ( id INT PRIMARY KEY, name VARCHAR(50) ); CREATE TABLE address
332 18
|
XML Java 数据库连接
Mybatis映射关系
简介:本文介绍了MyBatis框架中四种常见的关系映射方式,包括一对一、一对多、多对一及多对多。一对一通过简单属性映射实现;一对多通过在主对象中添加集合属性并使用`&lt;collection&gt;`标签映射子对象集合;多对一则利用`&lt;association&gt;`标签在主对象中映射单个子对象;多对多需引入第三方类,分别在两个主对象中添加对方的集合属性,并通过`&lt;collection&gt;`标签实现映射。
230 32
|
SQL 缓存 Java
【详细实用のMyBatis教程】获取参数值和结果的各种情况、自定义映射、动态SQL、多级缓存、逆向工程、分页插件
本文详细介绍了MyBatis的各种常见用法MyBatis多级缓存、逆向工程、分页插件 包括获取参数值和结果的各种情况、自定义映射resultMap、动态SQL
【详细实用のMyBatis教程】获取参数值和结果的各种情况、自定义映射、动态SQL、多级缓存、逆向工程、分页插件
mybatis复习04高级查询 一对多,多对一的映射处理,collection和association标签的使用
文章介绍了MyBatis中高级查询的一对多和多对一映射处理,包括创建数据库表、抽象对应的实体类、使用resultMap中的association和collection标签进行映射处理,以及如何实现级联查询和分步查询。此外,还补充了延迟加载的设置和用法。
mybatis复习04高级查询 一对多,多对一的映射处理,collection和association标签的使用
|
SQL Java 数据库连接
idea中配置mybatis 映射文件模版及 mybatis plus 自定义sql
idea中配置mybatis 映射文件模版及 mybatis plus 自定义sql
545 3
|
6月前
|
Java 数据库连接 数据库
Spring boot 使用mybatis generator 自动生成代码插件
本文介绍了在Spring Boot项目中使用MyBatis Generator插件自动生成代码的详细步骤。首先创建一个新的Spring Boot项目,接着引入MyBatis Generator插件并配置`pom.xml`文件。然后删除默认的`application.properties`文件,创建`application.yml`进行相关配置,如设置Mapper路径和实体类包名。重点在于配置`generatorConfig.xml`文件,包括数据库驱动、连接信息、生成模型、映射文件及DAO的包名和位置。最后通过IDE配置运行插件生成代码,并在主类添加`@MapperScan`注解完成整合
1095 1
Spring boot 使用mybatis generator 自动生成代码插件