【mybatis xml】数据层框架应用--Mybatis(四)关系映射之一对多关系映射

【mybatis xml】数据层框架应用--Mybatis(四)关系映射之一对多关系映射

实际的开发中,对数据库的操作常常会涉及到多张表,这在面向对象中就涉及到了对象与对象之间的关联关系。

针对多表之间的操作,MyBatis提供了关联映射,通过关联映射就可以很好的处理对象与对象之间的关联关系。

你需要了解的知识点

1、关联关系种类

数据库:

在关系型数据库中,多表之间存在着三种关联关系,分别为一对一一对多多对多

  1. 一对一:在任意一方引入对方主键作为外键;
  2. 一对多:在“多”的一方,添加“一”的一方的主键作为外键;
  3. 多对多:产生中间关系表,引入两张表的主键作为外键,两个主键成为联合主键或使用新的字段作为主键。

java

  1. 一对一:在本类中定义对方类型的对象,如A类中定义B类类型的属性b,B类中定义A类类型的属性a;(双向一对一)

  2. 一对多:一个A类类型对应多个B类类型的情况,需要在A类中以集合的方式引入B类类型的对象,在B类中定义A类类型的属性a;

  3. 多对多:在A类中定义B类类型的集合,在B类中定义A类类型的集合。

2、关联查询方式

MyBatis加载关联关系对象主要通过两种方式:嵌套查询嵌套结果

使用

项目目录如图,其中红色标注的为本次所需要的,本次主要讲解一对多关系映射,如果你对mybatis的xml版不熟悉的话请前往 数据层框架应用—Mybatis(一) 基于XML映射文件实现数据的CRUD 🔗

1、创建实体类

创建实体类:在com.lomtom.mybaris.entity包中创建实体类Type.javaProductInfo.java

1Type.java
/**
 * @Author: LOMTOM
 * @Date: 2020/4/26
 * @Time: 17:48
 * @Email: lomtom@lomtom.cn
 */
@Data
public class Type {
    private int id;

    private String name;

    private List<ProductInfo> pis;

    public Type() {
    }

    public Type(String name) {
        this.name = name;
    }
}

2ProductInfo.java
/**
 * @Author: LOMTOM
 * @Date: 2020/4/26
 * @Time: 17:48
 * @Email: lomtom@lomtom.cn
 */
@Data
public class ProductInfo {
    private int id;

    private String code;

    private String name;

    private Type t;

    public ProductInfo() {
    }

    public ProductInfo(String code, String name) {
        this.code = code;
        this.name = name;
    }
}

2、创建SQL映射的XML文件

创建SQL映射的XML文件typeMapper.xmlproductInfoMapper.xml

1、typeMapper.xml
	<mapper namespace="com.lomtom.mybatis.mapper.typeMapper">
	    <!--插入数据-->
	    <insert id="addType" parameterType="Type">
	        <!--获得刚插入数据表type的记录id-->
	        <selectKey keyProperty="id" resultType="int" order="AFTER">
	            SELECT LAST_INSERT_ID() AS ID
	        </selectKey>
	        insert into type(name) values(#{name})
	    </insert>
	
	    <!--加载数据(方式1)-->
	    <select id="getType" parameterType="int" resultMap="getTypeMap">
	        select t.id tid, t.name tname, pi.* from type t, product_info pi
	        where pi.tid=t.id and t.id=#{id}
	    </select>
	    <resultMap type="Type" id="getTypeMap">
	        <id property="id" column="tid"/>
	        <result property="name" column="tname"/>
	        <collection property="pis" ofType= "ProductInfo">
	            <id property="id" column="id"/>
	            <result property="code" column="code"/>
	            <result property="name" column="name"/>
	        </collection>
	    </resultMap>
	
	
	
	    <!--加载数据(方式2)-->
	    <select id="getType2" resultMap="getType2Map">
	        select * from type where id=#{id}
	    </select>
	    <resultMap type="Type" id="getType2Map">
	        <id property="id" column="id"/>
	        <result property="name" column="name"/>
	        <collection property="pis" column="id" select="getProductInfo"/>
	    </resultMap>
	    <select id="getProductInfo" resultMap="getProductInfoMap">
	        select from product info where tid=#{id}
	    </select>
	    <resultMap type="ProductInfo" id="getProductInfoMap">
	    <id property="id" column="id"/>
	    <result property="code" column="code"/>
	    <result property="name" column="name"/>
	    </resultMap>
	</mapper>


2、productInfoMapper.xml
	<mapper namespace="com.lomtom.mybatis.mapper.productInfoMapper">
	    <insert id="addProductInfo" parameterMap="addProductInfoPMap">
	        insert into product_info(code, name, tid) values(#{code},
	        #{name}, #{t.id})
	    </insert>
	    <parameterMap type="ProductInfo" id="addProductInfoPMap">
	        <parameter property="code"/>
	        <parameter property="name"/>
	        <parameter property="t.id"/>
	    </parameterMap>
	</mapper>

3、注册SQL映射的XML文件

在XML配置文件mybatis-config.xml中注册typeMapper.xml和productInfoMapper.xml。

    <mappers>
        <mapper resource="com/lomtom/mybatis/mapper/productInfoMapper.xml"/>
        <mapper resource="com/lomtom/mybatis/mapper/typeMapper.xml"/>
    </mappers>

4、创建表格

创建typeproduct_info两个表

1type
	SET NAMES utf8mb4;
	SET FOREIGN_KEY_CHECKS = 0;
	
	-- ----------------------------
	-- Table structure for type
	-- ----------------------------
	DROP TABLE IF EXISTS `type`;
	CREATE TABLE `type`  (
	  `id` int(0) NOT NULL AUTO_INCREMENT,
	  `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
	  PRIMARY KEY (`id`) USING BTREE
	) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;
	
	SET FOREIGN_KEY_CHECKS = 1;


2、product_info
	SET NAMES utf8mb4;
	SET FOREIGN_KEY_CHECKS = 0;
	
	-- ----------------------------
	-- Table structure for product_info
	-- ----------------------------
	DROP TABLE IF EXISTS `product_info`;
	CREATE TABLE `product_info`  (
	  `id` int(0) NOT NULL AUTO_INCREMENT,
	  `code` varchar(45) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
	  `name` varchar(45) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
	  `tid` int(0) NULL DEFAULT NULL,
	  PRIMARY KEY (`id`) USING BTREE,
	  INDEX `fk_product_type_idx`(`tid`) USING BTREE,
	  CONSTRAINT `product_info_ibfk_1` FOREIGN KEY (`tid`) REFERENCES `type` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT
	) ENGINE = InnoDB AUTO_INCREMENT = 16 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
	
	SET FOREIGN_KEY_CHECKS = 1;

5、测试一对一关联映射

在测试类里加入以下,用于测试我们刚刚写的插入与查询

  @Test
    public void testAddType(){
        SqlSession sqlSession= MybatisUtils.getSession();
        //创建Type对象
        Type type = new Type("打印机");
        //保存Type对象
        sqlSession.insert("addType", type);
        //创建两个 ProductInfo对象
        ProductInfo productInfo1=new ProductInfo( "111111", "HP1306");
        ProductInfo productInfo2=new ProductInfo( "222222","HP11103");
        //设置 ProductInfo对象与Type的关联
        productInfo1.setT(type);
        productInfo2.setT(type);
        //保存两个 ProductInfo对象
        sqlSession.insert("addProductInfo", productInfo1);
        sqlSession.insert("addProductInfo", productInfo2);
        sqlSession.commit();
        sqlSession.close();
    }

    @Test
    public void testGetTypeById() {
        SqlSession sqlSession= MybatisUtils.getSession();
        Type t = sqlSession.selectOne("getType", 1);
        System.out.println(t);
        sqlSession.commit();
        sqlSession.close();
    }


    @Test
    public void testGetTypeById2() {
        SqlSession sqlSession= MybatisUtils.getSession();
        Type t = sqlSession.selectOne(" getType2", 1);
        System.out.println(t);
        sqlSession.commit();
        sqlSession.close();
    }

你可能会出现的问题

问题一:提示缺少构造函数

描述:

Cause: org.apache.ibatis.executor.ExecutorException: No constructor found in com.lomtom.mybatis.entity.AdminInfo matching [java.lang.Integer, java.lang.String, java.lang.String, java.lang.String, java.lang.String]

分析:我们明明使用了lombok,为啥还会提示缺少构造函数,那是因为我们这里使用复杂的bean,lombok自己识别不出来 解决:AdminDetail.javaAdminInfo.java创造空的构造函数

写在最后

关注公众号:博奥思园 ,精彩内容不错失

你的支持是作者最大的动力

lomtom

标题:【mybatis xml】数据层框架应用--Mybatis(四)关系映射之一对多关系映射

作者:lomtom

链接:https://lomtom.cn/mybatis-xml数据层框架应用--mybatis四关系映射之一对多关系映射