提升开发效率的必备技能:深入理解Mybatis关系映射

简介: 提升开发效率的必备技能:深入理解Mybatis关系映射

bd940f942d114044811bf42d7e2adb1a.jpg

引言

在实际开发中,对数据库的操作常常会涉及到多张表,针对多表之间的操作,MyBatis 提供了关联映射,通过关联映射可以很好地处理表与表、对象与对象之间的关联关系。在关系型数据库中,表与表之间存在着三种关联映射关系,分别为一对一关系、一对多关系和多对多关系。

一、关系映射的概述

在 MyBatis 中,通过 association 元素来处理对象与对象之间关联关系,association 元素提供了一系列属性用于维护数据表之间的关系。association 元素是 resultMap元素的子元素,它有两种配置方式,嵌套查询方式和嵌套结果集方式。

属性 说明
column 表示数据库中的列名,对应实体类中的属性名。
property 表示实体类中的属性名,对应数据库中的列名。
collection 表示集合类型,对应实体类中的List、Set等集合类型
ofType 表示集合中元素的类型,用于指定集合中元素的类型。
association 表示一对一关联关系,对应实体类中的一个属性和一个数据库表中的一列。
javaType 表示Java中的数据类型,用于指定集合中元素的类型。

二、resultType与resultMap区别

这里我们假设一个场景,我们在开发项目的时候编写代码用的是嵌套结果集的方式,我们用的是resultType(resultType="com.csdn.xw.model.Book"),这个时候客户的需求是查出书籍名字和书籍价格,等你写完需求后面客户又变需求了,你为了方便写成resultType="java.util.Map",这时候不论客户什么时候该需求,我们的这串代码都不会变。时过境迁,你离开了原来的公司,后面来的开发者,看你写的代码并不会知道,你所接收的字段有什么,是书籍名字还是书籍名称和书籍价格等等,这就是不足之处。

通过上面的小故事我们总结一下:

使用 resultType,我们直接指定了查询结果的类型(这里是 "com.csdn.xw.model.Book"),它通常用于简单的查询语句,不需要复杂的映射关系。优点是简单直观,缺点是不能进行复杂的映射操作(实体类没有该属性的情况)。

而使用 resultMap,我们可以更加灵活地映射查询结果到任意类型的 Java 对象上。通过定义一个 resultMap,我们可以指定每个查询结果列与 Java 对象属性之间的映射关系。优点是功能强大,可以进行各种复杂的映射操作,缺点是需要编写更多的 XML 配置代码。

下面以嵌套结果集进行演示表与表之间存在着三种关联映射关系。

三、一对一关系查询

这里需要建一个VO类,VO是Value Object的缩写,是一种轻量级的数据结构,用于在视图层与业务逻辑层之间传递数据。VO通常用于表示视图层所需的数据,这些数据来自于业务逻辑层或数据访问层。VO的主要目的是将业务逻辑层的数据结构转换为视图层可以使用的数据结构 。简单来说就是用于关系映射时的结果接收。

下面我们利用订单项以及订单来描述一对一的关系,所以我们建立一个OrderitemVo。

public class OrderitemVo extends Orderitem {
    private Order order;
    public Order getOrder() {
        return order;
    }
    public void setOrder(Order order) {
        this.order = order;
    }

3.1.嵌套结果集编写

<resultMap id="OrderitemvoMap" type="com.csdn.xw.vo.OrderitemVo">
    <result column="order_item_id" property="orderItemId"></result>
    <result column="product_id" property="productId"></result>
    <result column="quantity" property="quantity"></result>
    <result column="oid" property="oid"></result>
    <association property="order" javaType="com.csdn.xw.model.Order">
      <result column="order_id" property="orderId"></result>
      <result column="order_no" property="orderNo"></result>
    </association>
  </resultMap>
  <select id="selectByOiid" resultMap="OrderitemvoMap" parameterType="java.lang.Integer">
    select * from t_hibernate_order o,t_hibernate_order_item oi where o.order_id=oi.oid and oi.order_item_id=#{oiid}
  </select>

3.2.案例测试

Biz编写

public interface OrderitemBiz {
    OrderitemVo selectByOiid(Integer oiid);
}

Impl编写

@Service
public class OrderitemImpl implements OrderitemBiz {
    @Autowired
    private OrderitemMapper OrderitemMapper;
    @Override
    public OrderitemVo selectByOiid(Integer oiid) {
        return OrderitemMapper.selectByOiid(oiid);
    }
}

Test测试

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"classpath:spring-context.xml"})
public class OrderitemImplTest {
    @Autowired
    private OrderitemBiz OrderitemBiz;
    @Test
    public void selectByOiid() {
        OrderitemVo orderitemVo = OrderitemBiz.selectByOiid(27);
        System.out.println(orderitemVo);
        System.out.println(orderitemVo.getOrder());
    }
}

测试结果:

四、一对多关系查询

下面我们利用订单以及订单项来描述一对多的关系,所以我们建立一个OrderVo。

public class OrderVo extends Order {
    private List<Orderitem> orderitems=new ArrayList<>();
    public List<Orderitem> getOrderitems() {
        return orderitems;
    }
    public void setOrderitems(List<Orderitem> orderitems) {
        this.orderitems = orderitems;
    }
    @Override
    public String toString() {
        return "OrderVo{" +
                "orderitems=" + orderitems +
                '}';
    }
}

4.1.嵌套结果集编写

 <resultMap id="OrderMap" type="com.csdn.xw.vo.OrderVo" >
    <result column="order_id" property="orderId"></result>
    <result column="order_no" property="orderNo"></result>
    <collection property="orderitems" ofType="com.csdn.xw.model.Orderitem">
      <result column="order_item_id" property="orderItemId"></result>
      <result column="product_id" property="productId"></result>
      <result column="quantity" property="quantity"></result>
      <result column="oid" property="oid"></result>
    </collection>
  </resultMap>
  <select id="byOid" resultMap="OrderMap" parameterType="java.lang.Integer" >
    select * from t_hibernate_order o,t_hibernate_order_item oi where o.order_id=oi.oid
     and o.order_id=#{oid}
  </select>

4.2.案例测试

Biz编写

public interface OrderBiz {
    OrderVo byOid(Integer id);
}

Impl编写

@Service
public class OrderBizImpl implements OrderBiz {
    @Autowired
    private OrderMapper orderMapper;
    @Override
    public OrderVo byOid(Integer id) {
        return orderMapper.byOid(id);
    }
}

Test编写

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"classpath:spring-context.xml"})
public class OrderBizImplTest {
@Autowired
private OrderBiz orderBiz;
    @Test
    public void byOid() {
        OrderVo orderVo = orderBiz.byOid(7);
        System.out.println(orderVo);
        orderVo.getOrderitems().forEach(System.out::println);
    }
}

测试结果:

五、多对多关系查询

我们以书籍有多个类别以及每个类别又有多本书的这种关系来实操多对多关系的查询

HbookVo

public class HbookVo  extends HBook {
    private List<HCategory> hcategory;
    public List<HCategory> getHcategory() {
        return hcategory;
    }
    public void setHcategory(List<HCategory> hcategory) {
        this.hcategory = hcategory;
    }
}

5.1.嵌套结果集编写

<resultMap id="HbookVo" type="com.csdn.xw.vo.HbookVo" >
    <result column="book_id" property="bookId"></result>
    <result column="book_name" property="bookName"></result>
    <result column="price" property="price"></result>
    <collection property="hcategory" ofType="com.csdn.xw.model.HCategory">
      <result column="category_id" property="categoryId"></result>
      <result column="category_name" property="categoryName"></result>
    </collection>
  </resultMap>
  <select id="selectByBid" resultMap="HbookVo" parameterType="java.lang.Integer">
    SELECT
  *
FROM
  t_hibernate_book b,
  t_hibernate_book_category bc,
  t_hibernate_category c
WHERE
  b.book_id = bc.bid
  AND bc.cid = c.category_id
  AND b.book_id =#{bid}
  </select>

5.1.案例测试

Biz编写

public interface HBookBiz {
    HbookVo selectByBid(Integer bid);
}

Impl编写

@Service
public class HBookBizImpl implements HBookBiz {
    @Autowired
    private HBookMapper hbookMapper;
    @Override
    public HbookVo selectByBid(Integer bid) {
        return hbookMapper.selectByBid(bid);
    }
}

Test编写

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"classpath:spring-context.xml"})
public class HBookBizImplTest {
    @Autowired
    private HBookBiz hbookBiz;
    @Test
    public void selectByBid() {
        HbookVo hbookVo = hbookBiz.selectByBid(8);
        System.out.println(hbookVo);
        hbookVo.getHcategory().forEach(System.out::println);
    }
}

测试结果:

六、总结

resultMap和resultType的区别在于,resultType是直接表示返回类型(基础类型、包装类型),而resultMap则是对外部ResultMap的引用。

Vo和Dto是两种不同的数据传输对象。Vo主要用于显示层与业务层之间的数据传递,而Dto主要用于远程调用时不同层之间的数据传递。

ofType和javaType都是MyBatis中的类型处理器,用于处理Java类型和JDBC类型之间的转换。其中,ofType用于处理集合类型,而javaType用于处理基本数据类型和JDBC类型。

使用场景:当查询结果为集合类型时,可以使用ofType;当查询结果为基本数据类型或JDBC类型时,可以使用javaType。

到这里我的分享就结束了,欢迎到评论区探讨交流!!

如果觉得有用的话还请点个赞吧 ♥  ♥


相关文章
|
1月前
|
SQL 缓存 Java
【详细实用のMyBatis教程】获取参数值和结果的各种情况、自定义映射、动态SQL、多级缓存、逆向工程、分页插件
本文详细介绍了MyBatis的各种常见用法MyBatis多级缓存、逆向工程、分页插件 包括获取参数值和结果的各种情况、自定义映射resultMap、动态SQL
【详细实用のMyBatis教程】获取参数值和结果的各种情况、自定义映射、动态SQL、多级缓存、逆向工程、分页插件
|
3月前
|
SQL XML Java
mybatis复习04高级查询 一对多,多对一的映射处理,collection和association标签的使用
文章介绍了MyBatis中高级查询的一对多和多对一映射处理,包括创建数据库表、抽象对应的实体类、使用resultMap中的association和collection标签进行映射处理,以及如何实现级联查询和分步查询。此外,还补充了延迟加载的设置和用法。
mybatis复习04高级查询 一对多,多对一的映射处理,collection和association标签的使用
|
2月前
|
前端开发 Java 数据库连接
表白墙/留言墙 —— 中级SpringBoot项目,MyBatis技术栈MySQL数据库开发,练手项目前后端开发(带完整源码) 全方位全步骤手把手教学
本文是一份全面的表白墙/留言墙项目教程,使用SpringBoot + MyBatis技术栈和MySQL数据库开发,涵盖了项目前后端开发、数据库配置、代码实现和运行的详细步骤。
67 0
表白墙/留言墙 —— 中级SpringBoot项目,MyBatis技术栈MySQL数据库开发,练手项目前后端开发(带完整源码) 全方位全步骤手把手教学
|
3月前
|
Java 数据库连接 数据格式
【Java笔记+踩坑】Spring基础2——IOC,DI注解开发、整合Mybatis,Junit
IOC/DI配置管理DruidDataSource和properties、核心容器的创建、获取bean的方式、spring注解开发、注解开发管理第三方bean、Spring整合Mybatis和Junit
【Java笔记+踩坑】Spring基础2——IOC,DI注解开发、整合Mybatis,Junit
|
4月前
|
SQL Java 数据库连接
Spring Boot联手MyBatis,打造开发利器:从入门到精通,实战教程带你飞越编程高峰!
【8月更文挑战第29天】Spring Boot与MyBatis分别是Java快速开发和持久层框架的优秀代表。本文通过整合Spring Boot与MyBatis,展示了如何在项目中添加相关依赖、配置数据源及MyBatis,并通过实战示例介绍了实体类、Mapper接口及Controller的创建过程。通过本文,你将学会如何利用这两款工具提高开发效率,实现数据的增删查改等复杂操作,为实际项目开发提供有力支持。
263 0
|
5月前
|
SQL Java 数据库连接
idea中配置mybatis 映射文件模版及 mybatis plus 自定义sql
idea中配置mybatis 映射文件模版及 mybatis plus 自定义sql
102 3
|
4月前
|
SQL Java 数据库连接
后端框架的学习----mybatis框架(7、使用注解开发)
这篇文章讲述了如何使用MyBatis框架的注解方式进行开发,包括在接口上使用注解定义SQL语句,并通过动态代理实现对数据库的增删改查操作,同时强调了接口需要在核心配置文件中注册绑定。
|
6月前
|
SQL XML Java
后端数据库开发JDBC编程Mybatis之用基于XML文件的方式映射SQL语句实操
后端数据库开发JDBC编程Mybatis之用基于XML文件的方式映射SQL语句实操
77 3
|
6月前
|
Java 数据库连接 API
后端开发之用Mybatis简化JDBC的开发快速入门2024及数据库连接池技术和lombok工具详解
后端开发之用Mybatis简化JDBC的开发快速入门2024及数据库连接池技术和lombok工具详解
68 3
|
6月前
|
SQL Java 数据库连接
2万字实操案例之在Springboot框架下基于注解用Mybatis开发实现基础操作MySQL之预编译SQL主键返回增删改查
2万字实操案例之在Springboot框架下基于注解用Mybatis开发实现基础操作MySQL之预编译SQL主键返回增删改查
84 2