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 的一些高级特性(如鉴别器、构造器映射等)

相关推荐
熙客21 小时前
TiDB:分布式关系型数据库
java·数据库·分布式·tidb
你想考研啊1 天前
linux安装jdk和tomcat和并自启动
java·linux·tomcat
悟能不能悟1 天前
java的java.sql.Date和java.util.Date的区别,应该怎么使用
java·开发语言
高山上有一只小老虎1 天前
java 正则表达式大全
java·正则表达式
_院长大人_1 天前
设计模式-工厂模式
java·开发语言·设计模式
凌波粒1 天前
MyBatis完整教程IDEA版(2)--ResultMap/注解/一对多/多对一/lombok/log4j
java·intellij-idea·mybatis
蓝-萧1 天前
【玩转全栈】----Django基本配置和介绍
java·后端
priority_key1 天前
排序算法:堆排序、快速排序、归并排序
java·后端·算法·排序算法·归并排序·堆排序·快速排序
汤姆yu1 天前
基于SpringBoot的动漫周边商场系统的设计与开发
java·spring boot·后端
皮皮林5511 天前
快速解决 Maven 版本冲突指南 !
java·maven