MyBatis的关系映射——多对多

本文介绍使用MyBatis实现多对多关系映射的方法,包括数据库设计、实体类定义、XML映射文件配置及测试过程。重点展示了两种查询方式:嵌套查询和嵌套结果查询。

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

MyBatis的关系映射——多对多

多对多的关系

在A类中定义B类类型的集合,在B类中定义A类类型的集合

这次的博客直接在上一篇MyBatis的关系映射——一对多的基础上写,直接添加相关文件就可以

1、创建相关数据库

create table tb_product(
id int(32) primary key auto_increment,
name varchar(32),
price double
);
insert into tb_product values ('1','Java fundment','44.5');
insert into tb_product values ('2','Java Web fundment','38.5');
insert into tb_product values ('3','SSM prictence','50');
create table tb_ordersitem(
id int(32) primary key auto_increment,
orders_id int(32),
product_id int(32),
foreign key(orders_id) references tb_orders(id),
foreign key(product_id) references tb_product(id)
);
insert into tb_ordersitem values ('1','1','1');
insert into tb_ordersitem values ('2','1','3');
insert into tb_ordersitem values ('3','3','3');

2、在com.po包中创建类Product并重写Orders类

package com.po;

import java.util.List;

public class Product {
    private Integer id;
    private String username;
    private Double price;
    private List<Orders> orders;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public Double getPrice() {
        return price;
    }

    public void setPrice(Double price) {
        this.price = price;
    }

    public List<Orders> getOrders() {
        return orders;
    }

    public void setOrders(List<Orders> orders) {
        this.orders = orders;
    }

    @Override
    public String toString() {
        return "Product{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", price=" + price +
                ", orders=" + orders +
                '}';
    }
}

重写Orders类的主要目的是为了方便查看数据结果

package com.po;

import java.util.List;

public class Orders {
    private Integer id;    
    private String number;
    private List<Product> productList;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getNumber() {
        return number;
    }

    public void setNumber(String number) {
        this.number = number;
    }

    public List<Product> getProductList() {
        return productList;
    }

    public void setProductList(List<Product> productList) {
        this.productList = productList;
    }

    @Override
    public String toString() {
        return "Orders{" +
                "id=" + id +
                ", number='" + number + '\'' +
                ", productList=" + productList +
                '}';
    }
}

3、在com.mapper中创建实体映射文件OrdersMapper.xml和商品实体映射文件ProductMapper.xml

OrdersMapper.xml如下所示
<?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="com.mapper.OrdersMapper">
	<!-- 多对多嵌套查询:通过执行另外一条SQL映射语句来返回预期的特殊类型 -->
	<select id="findOrdersWithProduct" parameterType="Integer"
              resultMap="OrdersWithProductResult">
		select * from tb_orders WHERE id=#{id}	
	</select>
	<resultMap type="Orders" id="OrdersWithProductResult">
		<id property="id" column="id" />
		<result property="number" column="number" />
		<collection property="productList" column="id" ofType="Product" 
		     select="com.mapper.ProductMapper.findProductById">
		</collection>
	</resultMap>
	
	<!-- 多对多嵌套结果查询:查询某订单及其关联的商品详情 -->
	<select id="findOrdersWithPorduct2" parameterType="Integer" 
	         resultMap="OrdersWithPorductResult2">
	    select o.*,p.id as pid,p.name,p.price
	    from tb_orders o,tb_product p,tb_ordersitem  oi
	    WHERE oi.orders_id=o.id 
	    and oi.product_id=p.id 
	    and o.id=#{id}
	</select>
	<!-- 自定义手动映射类型 -->
	<resultMap type="Orders" id="OrdersWithPorductResult2">
	    <id property="id" column="id" />
	    <result property="number" column="number" />
	    <!-- 多对多关联映射:collection -->
	    <collection property="productList" ofType="Product">
	        <id property="id" column="pid" />
	        <result property="name" column="name" />
	        <result property="price" column="price" />
	    </collection>
	</resultMap>
</mapper>
ProductMapper.xml如下所示
<?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="com.mapper.ProductMapper">
	<select id="findProductById" parameterType="Integer" 
                                       resultType="Product">
		SELECT * from tb_product where id IN(
		   SELECT product_id FROM tb_ordersitem  WHERE orders_id = #{id}
		)
	</select>
</mapper>

4、将新创建的映射文件的文件路径添加到配置文件Mybatis-config.xml中

<mapper resource="com/mapper/OrdersMapper.xml" />
<mapper resource="com/mapper/ProductMapper.xml" />
5、在测试类中编写多对多关联查询的测试方法findOrdersTest()
    @Test
    public void findOrdersTest(){
        SqlSession session=MybatisUtils.getSession();
        Orders orders=session.selectOne("com.mapper."+"OrdersMapper.findOrdersWithProduct",1);
        System.out.println(orders);
        session.close();
    }

运行结果如下
在这里插入图片描述

遇到的问题

在这次过程中遇到如下问题

org.apache.ibatis.exceptions.PersistenceException: 
### Error querying database.  Cause: java.lang.IllegalArgumentException: Mapped Statements collection does not contain value for com.mapper.OrdersMapper.findOrdersWithProduct
### Cause: java.lang.IllegalArgumentException: Mapped Statements collection does not contain value for com.mapper.OrdersMapper.findOrdersWithProduct

	at org.apache.ibatis.exceptions.ExceptionFactory.wrapException(ExceptionFactory.java:30)
	at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:150)
	at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:141)
	at org.apache.ibatis.session.defaults.DefaultSqlSession.selectOne(DefaultSqlSession.java:77)
	at com.test.MybatisAssociatedTest.findOrdersTest(MybatisAssociatedTest.java:36)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
	at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
	at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
	at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
	at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
	at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
Caused by: java.lang.IllegalArgumentException: Mapped Statements collection does not contain value for com.mapper.OrdersMapper.findOrdersWithProduct
	at org.apache.ibatis.session.Configuration$StrictMap.get(Configuration.java:933)
	at org.apache.ibatis.session.Configuration.getMappedStatement(Configuration.java:726)
	at org.apache.ibatis.session.Configuration.getMappedStatement(Configuration.java:719)
	at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:147)
	... 25 more

看到报错提示一直以为是数据库访问出现问题,删掉数据库重写一遍发现问题仍然存在,然后一直检查com.mapper.OrdersMapper.findOrdersWithProduct文档中的代码段发现并没有什么问题,谷歌了很多方案也并没有解决掉,当时放弃了,在看了几集《星际迷航:发现号》之后猛然发现这个地方出了问题
在这里插入图片描述应该是 id=“findOrdersWithProductResult” 结果成了 id=“findrOdersWithProduct” 改掉之后运行成功

写在最后

需要找一个开源项目好好练习,可以做一个二手商城交易系统,然后以此为蓝本再做一个推荐系统的小项目出来。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值