mybatis 关联关系映射《一对一》《多对一》《多对多》

这篇博客详细讲解了mybatis中一对一、一对多和多对多的关联关系映射。从概念理解到具体实现,包括数据库设计、resultType与resultMap的使用,以及在不同场景下的选择。通过示例代码和配置,展示了如何在mybatis中处理这些映射关系。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这段时间在学mybatis,到今天刚好是第五节课 关联关系映射,我记得先前学hibernate时,也有接触到映射一对多,多对一,多对多,虽说mybatis和hibernate均为持久层框架,但他们之间也有较大区别,比如说mybatis 属于轻量级,且半自动化,用sql,而hibernate数据重量级,且全自动化,用hql,个人感觉mybatis要高级点,也比较适用mybatis啦啦啦~

First (一对一) 

    首先我来说下一对一的理解,就是一个班主任只属于一个班级,一个班级也只能有一个班主任。这就是对于一对一的理解

怎么来实现呢?

这里我介绍了两种方式:

   一种是:使用嵌套结果映射来处理重复的联合结果的子集   

  另一种呢是:通过执行另外一个SQL映射语句来返回预期的复杂类型

<?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,namespace的值习惯上设置成包名+sql映射文件名,这样保证了namespace的值是唯一的-->
<mapper namespace="com.yc.mybatis.test.classMapper">
    
        <!-- 
         方式一:嵌套结果:使用嵌套结果映射来处理重复的联合结果的子集
                 封装联表查询的数据(去除重复的数据)
         select * from class c, teacher t where c.teacher_id=t.t_id and c.c_id=1
     -->
    
    <select id="getClass" parameterType="int" resultMap="getClassMap">
        select * from class c, teacher t  where c.teacher_id = t.t_id and c.teacher_id=#{id}
    </select>
    
    <!-- resultMap:映射实体类和字段之间的一一对应的关系 -->
    <resultMap type="Classes" id="getClassMap">
        <id property="id" column="c_id"/>   
        <result property="name" column="c_name"/>
        <association property="teacher" javaType="Teacher">   
            <id property="id" column="t_id"/>
            <result property="name" column="t_name"/>
        </association>
    </resultMap>
    
     <!-- 
         方式二:嵌套查询:通过执行另外一个SQL映射语句来返回预期的复杂类型
         SELECT * FROM class WHERE c_id=1;
         SELECT * FROM teacher WHERE t_id=1   //1 是上一个查询得到的teacher_id的值
         property:别名(属性名)    column:列名 -->
          <!-- 把teacher的字段设置进去 -->
    <select id="getClass1" parameterType="int" resultMap="getClassMap1">
        select * from class where c_id=#{id}
    </select>
    
    <resultMap type="Classes" id="getClassMap1">
        <id property="id" column="c_id"/>   
        <result property="name" column="c_name"/>
        <association property="teacher" column="teacher_id" select="getTeacher"/>   
    </resultMap>
    <select id="getTeacher" parameterType="int" resultType="Teacher">
        select t_id id,t_name name from teacher where t_id =#{id}
    </select>
</mapper>

 这里对assacation标签的属性进行解释一下:

property 对象属性的名称
javaType 对象属性的类型
column 所对应的外键字段名称
select 使用另一个查询封装的结果

 

这里bean层会发生变化 这个classes的被bean层会多一个Teacher的属性,并且增加的get,set方法。

resultType和resultMap实现一对一查询小结

 实现一对一查询:

  a.resultType:使用resultType实现较为简单,如果pojo中没有包括查询出来的列名,需要增加列名对应的属性,即可完成映射。

  b.如果没有查询结果的特殊要求建议使用resultType。

  c.resultMap:需要单独定义resultMap,实现有点麻烦,如果对查询结果有特殊的要求,使用resultMap可以完成将关联查询映射pojo的属性中。

  d.resultMap可以实现延迟加载,resultType无法实现延迟加载。

==============================================================================================

Second (一对多)and (多对一)

     一对多又是怎么样理解呢?

     其实也很容易,一个顾客对应多个订单,而一个订单只能对应一个客户

     而反过来也就是多对一的形式了

多个订单表可以对应一个顾客,一个顾客是可以拥有多个订单的

其实说到底就是有点类似多个一对一的情况,所以多对一的配置基本和一对一的配置保持一样

一、顾客表和订单表数据库(mysql)代码

-- 一对多
-- 客户表(主表)
create table t_customer
(
  customer_id int primary key not null auto_increment,
  customer_name varchar(50) not null
);

-- 多对一
-- 订单表(从表)
create table t_order
(
  order_id int primary key not null auto_increment,
  order_no varchar(50) not null unique,
  cid int not null,
  foreign key(cid) references t_customer(customer_id)
);


-- 初始化代码
delete from t_order;
delete from t_customer;

-- 与mssql不一样,自动增长是可以赋值,也可以不赋值
insert into t_customer(customer_id,customer_name) values(1, 'zs');
insert into t_customer(customer_id,customer_name) values(2, 'ls');
insert into t_customer(customer_id,customer_name) values(3, 'ww');
insert into t_customer(customer_id,customer_name) values(4, 'xm');

insert into t_order(order_no,cid) values('P01',1);
insert into t_order(order_no,cid) values('P02',1);
insert into t_order(order_no,cid) values('P03',1);
insert into t_order(order_no,cid) values('P04',1);
insert into t_order(order_no,cid) values('P05',1);
insert into t_order(order_no,cid) values('P06',2);
insert into t_order(order_no,cid) values('P07',2);
insert into t_order(order_no,cid) values('P08',2);
insert into t_order(order_no,cid) values('P09',3);
insert into t_order(order_no,cid) values('P10',3);



SELECT * FROM t_customer;
SELECT * FROM t_order;

二、因为我用的idea下载了插件,然后model包(有的人是pojo)mapper包,和XxxMapper.xml文件都是自动生成,需要者请参考我的博客<IntelliJ idea中简单配置的插件理解和使用:  https://blog.youkuaiyun.com/Fy_Deng/article/details/85985647  >

当生成了我们的一对多,多对一所以需要的model中实体类Customer.jave  Order.java

package com.zking.ssm.model;

import com.sun.org.apache.xml.internal.serializer.utils.SerializerMessages_sv;
import lombok.ToString;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

@ToString
public class Customer implements Serializable {
    private Integer customerId;

    private String customerName;

    private List<Order> orderList = new ArrayList<Order>();

    public Customer(Integer customerId, String customerName) {
        this.customerId = customerId;
        this.customerName = customerName;
    }

    public List<Order> getOrderList() {
        return orderList;
    }

    public void setOrderList(List<Order> orderList) {
        this.orderList = orderList;
    }

    public Customer() {
        super();
    }

    public Integer getCustomerId() {
        return customerId;
    }

    public void setCustomerId(Integer customerId) {
        this.customerId = customerId;
    }

    public String getCustomerName() {
        return customerName;
    }

    public void setCustomerName(String customerName) {
        this.customerName = customerName;
    }
}
package com.zking.ssm.model;

import lombok.ToString;

import java.io.Serializable;

@ToString
public class Order implements Serializable {
    private Integer orderId;

    private String orderNo;

    private Integer cid;

    private Customer customer;

    public Order(Integer orderId, String orderNo, Integer cid) {
        this.orderId = orderId;
        this.orderNo = orderNo;
        this.cid = cid;
    }

    public Customer getCustomer() {
        return customer;
    }

    public void setCustomer(Customer customer) {
        this.customer = customer;
    }

    public Order() {
        super();
    }

    public Integer getOrderId() {
        return orderId;
    }

  
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值