Mybatis一对一、一对多

目录

拥有Mybatis框架结构

准备相应的结构

在com.hz.pojo创建相应的实体类

一对一

一对多

resultMap和resultType

resultType

resultMap

对比总结

使用情景


拥有Mybatis框架结构

准备相应的结构

我们以bill表和provider表为例

在com.hz.pojo创建相应的实体类

User类:

java 复制代码
import java.math.BigDecimal;
import java.util.Date;

@Data
@ToString
public class Bill {
    private Integer id;
    private String billCode;
    private String productName;
    private String productDesc;
    private String productUnit;
    private BigDecimal productCount;
    private BigDecimal totalPrice;
    private Integer isPayment;
    private Integer providerId;
    private Integer createdBy;
    private Date creationDate;
    private Integer modifyBy;
    private Date modifyDate;

}

Provider类:

java 复制代码
package com.hz.pojo;

import lombok.Data;
import lombok.ToString;

import java.util.List;

@Data
@ToString
public class Provider {
    private Integer id; // 主键ID
    private String proCode;//供应商编码
    private String proName;//供应商名称
    private String proDesc;//供应商描述
    private String proContact;//供应商联系人
    private String proPhone;//供应商电话
    private String proAddress;//供应商地址
    private String proFax;//供应商传真
    private Integer createdBy;//创建者
    private String creationDate;//创建时间
    private Integer modifyBy;//修改者
    private String modifyDate;//修改时间

}

在com.hz.dao下建立相应的BillDao接口类和ProviderDao接口类

在resource.mappers建立相应的BillDao.xml 和ProviderDao.xml文件

在mybatis-config.xml里面的扫描相应的xml文件

一对一

表连接,Bill表为主表,provider表为子表

Bill表的providerId对应Provider表id

BillDao接口类:

public List<Bill> findBillList();

Bill类中添加相关子类provider的属性

private Integer providerId;

BillDao.xml:

java 复制代码
            <!-- 一对一   -->
    <select id="findBillList" resultMap="resultBill">
        select a.id,a.billCode,a.productName,a.productDesc,a.creationDate,b.id as bid,b.proCode ,b.proName
        from smbms_bill a
        left join smbms_provider b on a.providerId=b.id
    </select>
    <resultMap id="resultBill" type="Bill">
        <id property="id" column="id"/>
             <!-- property里面的是Bill类的    column里面是sql语句的       -->
        <result property="billCode" column="billCode"/>
        <result property="productName" column="productName"/>
        <result property="productDesc" column="productDesc"/>
        <result property="creationDate" column="creationDate"/>
              <!-- property是当前对象(通常是主表对应的实体类)中用来关联另一个对象(外键关系)的属性
                   javaType是property对象的类型  -->
        <association property="provider" javaType="Provider" >  <!-- resultMap="resultProvider"  可用于重复使用-->
            <id property="id" column="bid"/>
            <result property="proCode" column="proCode"/>
            <result property="proName" column="proName"/>
        </association>
    </resultMap>

测试代码:

java 复制代码
    @Test
    public void findBillList() {
        //读取mybatis主配置文件
            InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
            //获得sqlSession工厂
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
            //通过sqlSessionFactory获得数据库连接对象SqlSession
            SqlSession sqlSession = sqlSessionFactory.openSession(true);//默认true  自动提交
            //获得dao实例
             BillDao billDao = sqlSession.getMapper(BillDao.class);
        List<Bill> list = billDao.findBillList();
        list.forEach(s ->{
            System.out.println(s.toString());
        });
    }

一对多

表连接,provider表为主表,Bill表为子表

Provider表id对应Bill表的多个providerId

ProviderDao接口类:

public List<Provider> findProviderBillList( );

provider类中添加相关子类Bill的属性(一个provider数据对应多个bill数据,故bill为List):

private List<Bill> billList;

ProviderDao.xml:

java 复制代码
<select id="findProviderBillList" resultMap="ResultProviderBill">
        select a.id,a.proCode,a.proName,b.id as bid,b.billCode ,b.productName
        from smbms_provider a
        left join smbms_bill b on a.id=b.providerId
    </select>
    <resultMap id="ResultProviderBill" type="Provider">
        <id property="id" column="id"/>
        <result property="proCode" column="proCode"/>
        <result property="proName" column="proName"/>
        <!--  一对多 -->
        <!--  property里面是Provider类中一对多设置的集合billList
              ofType是property里面属性的类型   -->
        <collection property="billList" ofType="Bill">
            <id property="id" column="bid"/>
            <result property="billCode" column="billCode"/>
            <result property="productName" column="productName"/>
        </collection>
    </resultMap>

测试代码:

java 复制代码
    @Test
    public void findProviderBillList(){
                    //读取mybatis主配置文件
            InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
            //获得sqlSession工厂
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
            //通过sqlSessionFactory获得数据库连接对象SqlSession
            SqlSession sqlSession = sqlSessionFactory.openSession(true);//默认true  自动提交
            //获得dao实例
            ProviderDao providerDao = sqlSession.getMapper(ProviderDao.class);
        List<Provider> list = providerDao.findProviderBillList();
        list.forEach(s ->{
            System.out.println(s.toString());
            s.getBillList().forEach(b ->{
                System.out.println(b.toString());
            });
        });
    }

resultMap和resultType

在xml文件中的sql语句中有resultMap和resultType两种选择,接下来我们将介绍两种的特点和不同。

resultType

定义:

resultType是一个简单的配置项,用于指定查询结果直接映射到的 ​Java 类的全限定名(或别名)​ 。MyBatis 会 ​自动将查询结果的列名与 Java 对象的属性名进行匹配​(要求列名和属性名一致,或者通过开启驼峰命名等配置进行自动转换)。

特点:

  • 适用于 ​简单的POJO对象映射 ,即数据库字段名与Java对象的属性名完全一致或可通过配置匹配

  • 不能处理复杂的映射关系,比如:

    • 数据库字段名与Java属性名不一致(除非开启驼峰命名等自动映射)

    • 一对一、一对多等关联查询的复杂对象组装

    • 需要自定义类型处理的情况

resultMap

定义:

resultMap是 MyBatis 提供的一种 ​更加强大、灵活的映射机制 ,允许开发者 ​手动指定数据库的列与 Java 对象的属性之间的映射关系,支持复杂的映射,例如:

  • 列名与属性名不一致时进行显式映射

  • 嵌套结果映射(一对一、一对多关联)

  • 构造方法映射

  • 自动类型处理器、鉴别器(discriminator)等高级功能

特点:

  • 更加灵活,适合 ​复杂查询和对象关系映射

  • 可读性更高,特别是对于复杂SQL结果映射

  • 需要在XML中预先定义 <resultMap>,然后在查询中引用它

对比总结

对比维度 resultType resultMap
映射方式 自动映射(根据列名与属性名匹配) 手动指定列与属性的映射关系
灵活性 低,适用于简单对象 高,适用于复杂对象和关联查询
列名与属性名 必须一致(或通过配置如驼峰命名自动转换) 可以不一致,可手动指定 <result><id>
支持复杂映射 不支持(如一对一、一对多) 支持(通过 association、collection 等标签)
使用场景 简单查询,字段与属性名一致 复杂查询,字段与属性名不一致,有关联对象等
是否需要定义 否,直接写类全名 是,需要先定义 <resultMap>,再引用

使用情景

  • 使用 resultType 的情况:

    • 查询返回的是简单对象(如单个POJO)

    • 数据库的列名与Java对象的属性名完全一致,或可通过配置(如驼峰命名)自动匹配

    • 不需要处理复杂的对象关联(如一对一、一对多)

  • 使用 resultMap 的情况:

    • 数据库字段名与Java属性名不一致,且你不想或不能修改SQL或字段名

    • 查询涉及 复杂的对象关系(如一个用户有多个订单,或者包含部门信息等)

    • 你希望更 精确地控制映射逻辑

    • 你可能需要用到 MyBatis 的一些高级特性(如鉴别器、构造器映射等)

相关推荐
Andya_net3 小时前
Java | 基于redis实现分布式批量设置各个数据中心的服务器配置方案设计和代码实践
java·服务器·分布式
lang201509283 小时前
Spring Boot 外部化配置最佳实践指南
java·spring boot
沐浴露z3 小时前
【JVM】详解 垃圾回收
java·jvm·算法
重生之我要当java大帝4 小时前
java微服务-尚医通-管理平台前端搭建-医院设置管理-4
java·开发语言·前端
以己之4 小时前
详解TCP(详细版)
java·网络·tcp/ip
LiuYaoheng4 小时前
【Android】布局优化:include、merge、ViewStub的使用及注意事项
android·java
RealmElysia4 小时前
CoAlbum 引入ES
java·elasticsearch
せいしゅん青春之我4 小时前
[JavaEE初阶]网络协议-状态码
java·网络协议·http
shepherd1114 小时前
JDK源码深潜(一):从源码看透DelayQueue实现
java·后端·代码规范