java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > mybatis关联关系映射

mybatis关联关系映射的实现

作者:Ar.小白

MyBatis的关联关系映射在复杂数据模型中至关重要,使开发人员能够以最灵活的方式满足不同项目的需求,本文就来介绍一下mybatis关联关系映射的实现,感兴趣的可以了解一下

1. 介绍

在当今的软件开发中,与数据库进行交互是一项至关重要的任务。开发人员需要能够轻松、高效地执行数据库操作,同时又要保持代码的可维护性和灵活性。这正是MyBatis这个数据库访问框架应运而生的背景所在。

背景

数据库是许多应用程序的核心组成部分,用于存储和管理数据。然而,与数据库进行交互通常涉及到编写大量的SQL查询语句,以及处理结果集和数据库连接等繁琐的任务。这不仅使开发工作复杂化,还容易引入安全漏洞和性能问题。

在过去,JDBC(Java Database Connectivity)是与数据库交互的主要方式,它要求开发人员手动管理数据库连接、编写SQL语句和处理结果集。这种方式存在以下挑战:

MyBatis的出现解决了这些问题,为Java开发人员提供了一个强大的数据库访问框架,它背后的核心理念是将SQL语句从Java代码中解耦,同时提供了丰富的映射和查询功能。

MyBatis的特点

MyBatis具有许多优点,使其成为数据库访问的首选框架之一:

在数据库中,数据通常存储在多个相关联的表中,这些表之间存在各种复杂的关系,如一对一、一对多和多对多。为了有效地操作这些复杂的数据模型,引入了关联关系映射的概念,它在复杂数据模型中扮演着至关重要的角色。

什么是关联关系映射?

关联关系映射是将多个表之间的关联关系映射到程序中的对象模型的过程。它的核心目标是:

这个概念的核心思想是将数据库的复杂性隐藏在应用程序的背后,使开发人员能够更自然地处理数据,而不必深入了解数据库的结构和关系。

为什么关联关系映射在复杂数据模型中重要?

在复杂的数据模型中,表之间的关系往往非常复杂,可能包括:

一对一关系: 例如,一个用户只有一个个人详细信息,或一个订单只有一个送货地址。

一对多关系: 例如,一个作者可以有多本书,一个班级可以有多名学生。

多对多关系: 例如,多名学生可以选择多门课程,需要通过关联表进行映射。

在处理这些复杂的关系时,直接使用原始的SQL查询和结果集映射将变得非常繁琐和复杂。这里是为什么关联关系映射如此重要的原因:

总之,关联关系映射在复杂数据模型中是非常重要的,它提供了一种更高级、更抽象的方式来处理数据库操作,使开发人员能够更轻松地应对复杂性,提高代码的可维护性和开发效率。这正是许多现代应用程序开发中不可或缺的一部分。

2. 一对一关系映射

一对一关系映射是指两个实体之间存在唯一的对应关系,即一个实体只能与另一个实体相对应。例如,一个人只能有一个身份证号码,一个身份证号码也只能对应一个人。

一对一关系映射: 在数据库中,可以通过在一个实体表中添加一个外键来映射一对一关系。例如,假设我们有两个实体表:Person(人)和IDCard(身份证)。每个人只能有一个身份证,而每个身份证也只能对应一个人。我们可以在Person表中添加一个外键IDCardID,将其与IDCard表的主键IDCardID关联起来。这样,每个Person实体都会有一个唯一的IDCardID,从而建立了一对一的关系。

 配置generatoeConfig文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE generatorConfiguration PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
        "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd" >
<generatorConfiguration>
    <!-- 引入配置文件 -->
    <properties resource="jdbc.properties"/>
    <!--指定数据库jdbc驱动jar包的位置-->
    <classPathEntry location="C:\\temp2\\mvn_repository\\mysql\\mysql-connector-java\\5.1.44\\mysql-connector-java-5.1.44.jar"/>
    <!-- 一个数据库一个context -->
    <context id="infoGuardian">
        <!-- 注释 -->
        <commentGenerator>
            <property name="suppressAllComments" value="true"/><!-- 是否取消注释 -->
            <property name="suppressDate" value="true"/> <!-- 是否生成注释代时间戳 -->
        </commentGenerator>
        <!-- jdbc连接 -->
        <jdbcConnection driverClass="${jdbc.driver}"
                        connectionURL="${jdbc.url}" userId="${jdbc.username}" password="${jdbc.password}"/>
        <!-- 类型转换 -->
        <javaTypeResolver>
            <!-- 是否使用bigDecimal, false可自动转化以下类型(Long, Integer, Short, etc.) -->
            <property name="forceBigDecimals" value="false"/>
        </javaTypeResolver>
        <!-- 01 指定javaBean生成的位置 -->
        <!-- targetPackage:指定生成的model生成所在的包名 -->
        <!-- targetProject:指定在该项目下所在的路径  -->
        <javaModelGenerator targetPackage="com.zking.model"
                            targetProject="src/main/java">
            <!-- 是否允许子包,即targetPackage.schemaName.tableName -->
            <property name="enableSubPackages" value="false"/>
            <!-- 是否对model添加构造函数 -->
            <property name="constructorBased" value="true"/>
            <!-- 是否针对string类型的字段在set的时候进行trim调用 -->
            <property name="trimStrings" value="false"/>
            <!-- 建立的Model对象是否 不可改变  即生成的Model对象不会有 setter方法,只有构造方法 -->
            <property name="immutable" value="false"/>
        </javaModelGenerator>
        <!-- 02 指定sql映射文件生成的位置 -->
        <sqlMapGenerator targetPackage="com.zking.mapper"
                         targetProject="src/main/java">
            <!-- 是否允许子包,即targetPackage.schemaName.tableName -->
            <property name="enableSubPackages" value="false"/>
        </sqlMapGenerator>
        <!-- 03 生成XxxMapper接口 -->
        <!-- type="ANNOTATEDMAPPER",生成Java Model 和基于注解的Mapper对象 -->
        <!-- type="MIXEDMAPPER",生成基于注解的Java Model 和相应的Mapper对象 -->
        <!-- type="XMLMAPPER",生成SQLMap XML文件和独立的Mapper接口 -->
        <javaClientGenerator targetPackage="com.zking.mapper"
                             targetProject="src/main/java" type="XMLMAPPER">
            <!-- 是否在当前路径下新加一层schema,false路径com.oop.eksp.user.model, true:com.oop.eksp.user.model.[schemaName] -->
            <property name="enableSubPackages" value="false"/>
        </javaClientGenerator>
        <!-- 配置表信息 -->
        <!-- schema即为数据库名 -->
        <!-- tableName为对应的数据库表 -->
        <!-- domainObjectName是要生成的实体类 -->
        <!-- enable*ByExample是否生成 example类 -->
        <!--<table schema="" tableName="t_book" domainObjectName="Book"-->
        <!--enableCountByExample="false" enableDeleteByExample="false"-->
        <!--enableSelectByExample="false" enableUpdateByExample="false">-->
        <!--&lt;!&ndash; 忽略列,不生成bean 字段 &ndash;&gt;-->
        <!--&lt;!&ndash; <ignoreColumn column="FRED" /> &ndash;&gt;-->
        <!--&lt;!&ndash; 指定列的java数据类型 &ndash;&gt;-->
        <!--&lt;!&ndash; <columnOverride column="LONG_VARCHAR_FIELD" jdbcType="VARCHAR" /> &ndash;&gt;-->
        <!--</table>-->
        <table schema="" tableName="t_hibernate_book" domainObjectName="HBook"
               enableCountByExample="false" enableDeleteByExample="false"
               enableSelectByExample="false" enableUpdateByExample="false">
        </table>
        <table schema="" tableName="t_hibernate_book_category" domainObjectName="HBookCategory"
               enableCountByExample="false" enableDeleteByExample="false"
               enableSelectByExample="false" enableUpdateByExample="false">
        </table>
        <table schema="" tableName="t_hibernate_category" domainObjectName="HCategory"
               enableCountByExample="false" enableDeleteByExample="false"
               enableSelectByExample="false" enableUpdateByExample="false">
        </table>
        <table schema="" tableName="t_hibernate_order" domainObjectName="Order"
               enableCountByExample="false" enableDeleteByExample="false"
               enableSelectByExample="false" enableUpdateByExample="false">
        </table>
        <table schema="" tableName="t_hibernate_order_item" domainObjectName="OrderItem"
               enableCountByExample="false" enableDeleteByExample="false"
               enableSelectByExample="false" enableUpdateByExample="false">
        </table>
    </context>
</generatorConfiguration>

OrderItemVo

package com.liao.vo;
import com.liao.model.Order;
import com.liao.model.OrderItem;
public class OrderItemVo extends OrderItem {
    private Order order;
    public Order getOrder() {
        return order;
    }
    public void setOrder(Order order) {
        this.order = order;
    }
}
 

OrderItemMapper.xml

<resultMap id="OrderItemMap" type="com.liao.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.liao.model.Order">
      <result column="order_id" property="orderId" ></result>
      <result column="order_no" property="orderNo" ></result>
    </association>
  </resultMap>
  <select id="selectByBiid" resultMap="OrderItemMap" 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>

OrderItemBiz

package com.liao.biz;
import com.liao.vo.OrderItemVo;
public interface OrderItemBiz {
    OrderItemVo selectByBiid(Integer oiid);
}

实现OrderItemBiz接口,创建 OrderItemBizImpl 

package com.liao.biz;
import com.liao.mapper.OrderItemMapper;
import com.liao.vo.OrderItemVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class OrderItemBizImpl implements OrderItemBiz {
    @Autowired
    private OrderItemMapper orderItemMapper;
    @Override
    public OrderItemVo selectByBiid(Integer oiid) {
        return orderItemMapper.selectByBiid(oiid);
    }
}

测试

package com.liao.biz;
import com.liao.vo.OrderItemVo;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"classpath:spring-context.xml"})
public class Test01 {
    @Autowired
    private OrderItemBiz orderItemBiz;
    @Before
    public void setUp() throws Exception {
    }
    @After
    public void tearDown() throws Exception {
    }
    @Test
    public void selectByBiid() {
        OrderItemVo orderItemVo = orderItemBiz.selectByBiid(27);
        System.out.println(orderItemVo);
        System.out.println(orderItemVo.getOrder());
    }
}

3. 一对多关系映射

一对多关系映射是指一个实体可以与多个实体相对应,而多个实体只能与一个实体相对应。例如,一个班级可以有多个学生,但一个学生只能属于一个班级。

一对多关系映射: 在数据库中,可以通过在多的一方实体表中添加一个外键来映射一对多关系。例如,假设我们有两个实体表:Department(部门)和Employee(员工)。一个部门可以有多个员工,而一个员工只能属于一个部门。我们可以在Employee表中添加一个外键DepartmentID,将其与Department表的主键DepartmentID关联起来。这样,每个Employee实体都会有一个对应的DepartmentID,从而建立了一对多的关系。

OrdeVo

package com.liao.vo;
import com.liao.model.Order;
import com.liao.model.OrderItem;
import java.util.ArrayList;
import java.util.List;
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;
    }
}

OrderMapper.xml 

<resultMap id="OrderVoMap" type="com.liao.vo.OrderVo">
    <result column="order_id" property="orderId" ></result>
    <result column="order_no" property="orderNo" ></result>
    <collection property="orderItems" ofType="com.liao.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="selectByOid" resultMap="OrderVoMap" 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>

在自动生成的 OrderMapper接口中进行增加以下代码,如下:

OrderVo selectByOid(@Param("oid") Integer oid);

OrderBiz 接口

package com.liao.biz;
import com.liao.vo.OrderVo;
public interface OrderBiz {
    OrderVo selectByOid(Integer oid);
}

实现 OrderBiz 接口 创建 OrderBizImpl 

package com.liao.biz;
import com.liao.mapper.OrderMapper;
import com.liao.vo.OrderVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class OrderBizImpl implements OrderBiz {
    @Autowired
    private OrderMapper orderMapper;
    @Override
    public OrderVo selectByOid(Integer oid) {
        return orderMapper.selectByOid(oid);
    }
}

测试

   @Autowired
    private OrderBiz orderBiz;
    @Test
    public void selectByOid() {
        OrderVo orderVo = orderBiz.selectByOid(7);
        System.out.println(orderVo);
        orderVo.getOrderItems().forEach(System.out::println);

4. 多对多关系映射

多对多关系映射是指两个实体之间存在多对多的对应关系,即一个实体可以与多个实体相对应,同时一个实体也可以与多个实体相对应。例如,一个学生可以选择多门课程,而一门课程也可以有多个学生选修。在数据库中,多对多关系通常需要通过引入第三个实体(中间表)来实现。

多对多关系映射: 在数据库中,多对多关系通常需要通过引入第三个实体(中间表)来实现。例如,假设我们有两个实体表:Student(学生)和Course(课程)。一个学生可以选择多门课程,而一门课程也可以有多个学生选修。我们可以创建一个名为StudentCourse的中间表,其中包含两个外键:StudentID和CourseID,分别与Student表和Course表的主键关联起来。这样,每个学生可以在StudentCourse表中有多个对应的CourseID,同时每门课程也可以在StudentCourse表中有多个对应的StudentID,从而建立了多对多的关系。

HBookMapper.xml

<resultMap id="HBookVoMap" type="com.liao.vo.HbookVo" >
    <result column="book_id" property="bookId"></result>
    <result column="book_name" property="bookName"></result>
    <result column="price" property="price"></result>
    <collection property="categories" ofType="com.liao.model.Category">
      <result column="category_id" property="categoryId"></result>
      <result column="category_name" property="categoryName"></result>
    </collection>
  </resultMap>
  <select id="selectByBookId" resultMap="HBookVoMap" 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>

HBookMapper 

HbookVo selectByBookId(@Param("bid") Integer bid);

创建 HBookBiz 

package com.liao.biz;
import com.liao.vo.HbookVo;
import org.apache.ibatis.annotations.Param;
public interface HBookBiz {
    HbookVo selecByBookId(@Param("bid") Integer bid);
}

实现 HBookBiz 接口,创建 HBookBizImpl 

package com.liao.biz;
import com.liao.mapper.HBookMapper;
import com.liao.vo.HbookVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class HBookBizImpl implements HBookBiz {
    @Autowired
    private HBookMapper hBookMapper;
    @Override
    public HbookVo selecByBookId(Integer bid) {
        return hBookMapper.selectByBookId(bid);
    }
}

测试

 @Autowired
    private HBookBiz hbookBiz;
    @Test
    public void selectByBookId() {
        HbookVo hBookVo = hbookBiz.selecByBookId(8);
        System.out.println(hBookVo);
        hBookVo.getCategories().forEach(System.out::println);

5. 总结

MyBatis是一个强大的数据库访问框架,其中的关联关系映射是其核心功能之一。在处理复杂的数据模型时,MyBatis关联关系映射具有重要性和灵活性,如下所总结:

重要性:

1. 数据模型的抽象:

2. 提高可维护性:

3. 提高开发效率:

4. 增加灵活性:

5. 降低错误风险:

灵活性:

1. 一对一、一对多和多对多关系:

2. 动态SQL:

3. 自定义查询:

4. 延迟加载:

综上所述,MyBatis的关联关系映射在复杂数据模型中至关重要,因为它提供了一种更高级、更抽象的方式来处理数据库操作,同时也提供了丰富的配置和扩展选项,使开发人员能够以最灵活的方式满足不同项目的需求。它不仅提高了代码的可维护性和开发效率,还降低了错误风险,使开发人员能够更轻松地应对复杂性,是现代应用程序开发中不可或缺的工具之一。

到此这篇关于mybatis关联关系映射的实现的文章就介绍到这了,更多相关mybatis关联关系映射内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文