Mybatis的一对多、多对一、多对多案例
一、一对多
1.首先创建数据库和表。两张表的id字段是自动递增的。
给category表录入两条数据,可自行添加记录。
INSERT INTO `category` VALUES (1, '我是分类1');
INSERT INTO `category` VALUES (2, '我是分类2');
INSERT INTO `product` VALUES (1, '我是分类1下的商品1', 999.20, 1);
INSERT INTO `product` VALUES (2, '我是分类1下的第二个商品', 666.30, 1);
INSERT INTO `product` VALUES (3, '我是分类2的第一个商品', 56.30, 2);
INSERT INTO `product` VALUES (4, '我是分类2下的第二个商品', 79.60, 2);
2.使用IDEA创建maven项目。下面一步步创建文件模拟一对多,
项目实现一对多、多以对、多对多最终结构图如下图:
添加依赖和jdk编译版本:
<dependencies><!--数据库连接驱动--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.46</version></dependency><!--mybatis--><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.3.0</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version></dependency>
</dependencies><!--配置编译源代码的jdk版本-->
<build><plugins><plugin><artifactId>maven-compiler-plugin</artifactId><configuration><source>1.8</source><target>1.8</target></configuration></plugin></plugins>
</build>
3.创建和数据库表对应的pojo。
这个实体中新加了一个数据库没有的字段products,用于存放分类对应的商品集合。public class Category {private int id;private String name;private List<Product> products;public List<Product> getProducts() {return products;}public void setProducts(List<Product> products) {this.products = products;}public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}@Overridepublic String toString() {return "Category{" +"id=" + id +", name='" + name + '\'' +'}';}
}
这个实体目前还未加新的字段。
public class Product {private int id;private String name;private float price;public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public float getPrice() {return price;}public void setPrice(float price) {this.price = price;}@Overridepublic String toString() {return "Product{" +"id=" + id +", name='" + name + '\'' +", price=" + price +'}';}
}
4.创建mybatis的配置文件。
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration><typeAliases> <!--设置别名--><package name="com.byh.pojo"/></typeAliases><!--连接数据库--><environments default="development"><environment id="development"><transactionManager type="JDBC"/><dataSource type="POOLED"><property name="driver" value="com.mysql.jdbc.Driver"/><property name="url" value="jdbc:mysql://localhost:3306/dbmybatis?characterEncoding=UTF-8"/><property name="username" value="root"/><property name="password" value="admin"/></dataSource></environment></environments><!--扫描mapper文件--><mappers><mapper resource="mapper/CategoryMapper.xml"/></mappers></configuration>
5.创建CategoryMapper.xml。注意:namespace的值要是对应的mapper接口。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="com.byh.mapper.CategoryMapper"><resultMap type="Category" id="categoryBean"><id column="cid" property="id" /><result column="cname" property="name" /><!-- 一对多的关系 --><!-- property: 指的是集合属性的值, ofType:指的是集合中元素的类型 --><collection property="products" ofType="Product"><id column="pid" property="id" /><result column="pname" property="name" /><result column="price" property="price" /></collection></resultMap><!-- 关联查询分类和商品表通过left join关联查询,对Category和Product表进行关联查询。这里不是用的resultType, 而是resultMap,通过resultMap把数据取出来放在对应的对象属性里,通过指定列名映射实体具体的字段赋值。Category的id 字段 和Product的id字段同名,Mybatis不知道谁是谁的,所以需要通过取别名cid,pid来区分。name字段同理。--><select id="list" resultMap="categoryBean">select c.id as 'cid', c.name as 'cname',p.id as 'pid', p.name as 'pname' ,p.pricefromcategory c left join product ponc.id = p.cid</select></mapper>
6.创建CategoryMapper.java接口。
public interface CategoryMapper {List<Category> list();}
7.测试一对多关系。
import com.byh.mapper.CategoryMapper;
import com.byh.pojo.Category;
import com.byh.pojo.Product;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Before;
import org.junit.Test;import java.io.IOException;
import java.io.InputStream;
import java.util.List;public class Demo2 {private SqlSession session;private CategoryMapper categoryMapper;@Beforepublic void bef() throws IOException {//读取mybatis配置文件InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");//构建sqlSession的工厂SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);//创建能执行映射文件中sql的sqlSessionsession=sessionFactory.openSession();//获得mappercategoryMapper = session.getMapper(CategoryMapper.class);}@Testpublic void test(){List<Category> list = categoryMapper.list();for(Category c : list){System.out.println(c);List<Product> products = c.getProducts();for(Product product : products){System.out.println("\t"+product);}System.out.println("当前循环结束");}}}
二、多以一
1.接着上面的项目写,在Product.java中添加分类字段:记得都要添加get、set方法。
2.创建ProductMapper.java接口。
package com.byh.mapper;import com.byh.pojo.Product;import java.util.List;public interface ProductMapper {List<Product> productList();
}
3.创建对应的mapper.xml。ProductMapper.xml如下:
注意这里多对一中指定属性类型用的是javaType,跟一对多不一样。namespace中也要指定到对应的mapper接口的完整位置。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.byh.mapper.ProductMapper"><resultMap id="productBean" type="Product"><id column="pid" property="id"/><result column="pname" property="name"/><!-- 多以一 --><!-- property: 指的是属性名称, javaType:指的是属性的类型 --><association property="category" javaType="Category"><id column="cid" property="id"/><result column="cname" property="name"/></association></resultMap><select id="productList" resultMap="productBean">select c.id as 'cid', c.name as 'cname',p.id as 'pid', p.name as 'pname' ,p.pricefromcategory c left join product ponc.id = p.cid</select></mapper>
4.测试:在之前的demo中添加ProductMapper。
添加测试方法:
@Test
public void test02(){List<Product> list = productMapper.productList();for(Product p : list){System.out.println(p+"对应的分类:"+p.getCategory());}
}
结果:
三、多对多
1.数据库再新建两张表:
录入模拟多对多的数据:
INSERT INTO `order` VALUES (1, '编号A');
INSERT INTO `order` VALUES (2, '编号B');
INSERT INTO `order_item` VALUES (null, 1, 1, 52);
INSERT INTO `order_item` VALUES (null, 1, 2, 53);
INSERT INTO `order_item` VALUES (null, 1, 3, 54);
INSERT INTO `order_item` VALUES (null, 2, 2, 55);
INSERT INTO `order_item` VALUES (null, 2, 3, 56);
INSERT INTO `order_item` VALUES (null, 2, 4, 57);
2.创建两个实体:Order.java,其中添加了orderItemList字段,表示订单下的订单项。
public class Order {private int id;private String code;//表明订单中有哪些订单项private List<OrderItem> orderItemList;public int getId() {return id;}public void setId(int id) {this.id = id;}public String getCode() {return code;}public void setCode(String code) {this.code = code;}public List<OrderItem> getOrderItemList() {return orderItemList;}public void setOrderItemList(List<OrderItem> orderItemList) {this.orderItemList = orderItemList;}
}
和OrderItem.java,注意这里跟数据库中有两个字段不一样,这里用的是对应的实体。product、order。
public class OrderItem {private int id;private int number;//这里添加了商品和订单,用于表明一个订单项属于中具体是哪个商品和在哪个订单中private Product product;private Order order;public int getId() {return id;}public void setId(int id) {this.id = id;}public int getNumber() {return number;}public void setNumber(int number) {this.number = number;}public Product getProduct() {return product;}public void setProduct(Product product) {this.product = product;}public Order getOrder() {return order;}public void setOrder(Order order) {this.order = order;}
}
3.创建OrderMapper.xml,这里的resultMap我个人觉得绕了一点,但是理清思路也就感觉缺一不可。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.byh.mapper.OrderMapper"><!--这里比较绕查询后id和code字段放在Order对象里,然后通过一对多的<collection>标签把oiid和number放在OrderItem对象里,最后把pid,pname,price放进Product对象里--><resultMap id="orderBean" type="Order"><id column="oid" property="id"/><result column="code" property="code"/><!--这里关联订单和所属的订单项的数据 一对多 --><collection property="orderItemList" ofType="OrderItem"><id column="oiid" property="id" /><result column="number" property="number" /><!-- 订单项和商品是多对一 --><association property="product" javaType="Product"><id column="pid" property="id"/><result column="pname" property="name"/><result column="price" property="price"/></association></collection></resultMap><select id="orderList" resultMap="orderBean">select o.id 'oid',o.code, oi.id 'oiid',oi.number, p.name 'pname', p.id 'pid',p.pricefrom `order` oleft join order_item oi on o.id =oi.oidleft join product p on p.id = oi.pid</select></mapper>
4.写对应的order的接口。这里只有一个list的接口。
public interface OrderMapper {List<Order> orderList();}
5.一定要记得把xml文件添加到mybatis的映射文件中,不然会报错。
.
6.测试。在demo2.java中获得ordermapper。并调用orderList方法。
@Test
public void test03(){List<Order> os = orderMapper.orderList();//订单列表for (Order o : os) {System.out.println(o.getCode());//所有订单编号List<OrderItem> ois= o.getOrderItemList();//每个订单下的订单项for (OrderItem oi : ois) {//每个订单项下的商品信息System.out.println("商品:"+oi.getProduct().getName()+" 价格:"+oi.getProduct().getPrice()+" 数量:"+oi.getNumber());}}
}
输出结果:
接下来做添加订单项的准备工作:
1.创建OrderItemMapper.xml,加入增加和删除的查询:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.byh.mapper.OrderItemMapper"><insert id="addOrderItem" parameterType="OrderItem">insert into order_item values(null,#{order.id},#{product.id},#{number})</insert><insert id="delOrderItem" parameterType="OrderItem">delete from order_item where oid = #{order.id} and pid = #{product.id}</insert></mapper>
2.创建OrderItemMapper接口。
public interface OrderItemMapper {void addOrderItem(OrderItem orderItem);void delOrderItem(OrderItem orderItem);
}
3.mybatis加入配置文件。
4.OrderMapper.xml加入:
<select id="getOrder" resultMap="orderBean">select o.id 'oid',o.code, oi.id 'oiid',oi.number, p.name 'pname', p.id 'pid',p.pricefrom `order` oleft join order_item oi on o.id =oi.oidleft join product p on p.id = oi.pidwhere o.id=#{id}
</select>
OrderMapper接口中添加方法:
ProductMapper.xml同理:
<select id="getProduct" resultMap="productBean">select c.id as 'cid', c.name as 'cname',p.id as 'pid', p.name as 'pname' ,p.pricefromcategory c left join product ponc.id = p.cidwhere p.id=#{id}
</select>
5.测试添加订单和删除订单:
引入新的mapper:
测试方法:
@Test //添加订单项
public void test04(){order();//调用上面的查询所有订单的方法System.out.println("-----------------------------添加新的订单项后----------------------------:");Product p = productMapper.getProduct(1);Order o = orderMapper.getOrder(2);OrderItem orderItem = new OrderItem();orderItem.setOrder(o);//设置订单项所属订单orderItem.setProduct(p);//订单项所属商品orderItem.setNumber(1001);orderItemMapper.addOrderItem(orderItem);order();//不加这两句 添加的数据是不会应用到数据库的session.commit();session.close();
}@Test
public void del(){order();//调用上面的查询所有订单的方法System.out.println("-----------------------------删除订单项后----------------------------:");Product p = productMapper.getProduct(1);Order o = orderMapper.getOrder(2);OrderItem orderItem = new OrderItem();orderItem.setOrder(o);//设置订单项所属订单orderItem.setProduct(p);//订单项所属商品orderItemMapper.delOrderItem(orderItem);order();session.commit();session.close();
}
最后做一个删除订单就删除对应订单下的订单项的例子:
1.OrderMapper.xml中添加:
<delete id="delOrder" parameterType="int" >delete from order_item where oid = #{id};delete from `order` where id= #{id};
</delete>
OrderMapper接口中添加:
2.测试方法:
@Test
public void delOrder(){order();//调用上面的查询所有订单的方法orderMapper.delOrder(2);System.out.println("------------删除订单后:订单项也删除了---------------");order();//调用上面的查询所有订单的方法session.commit();session.close();
}
报错:org.apache.ibatis.exceptions.PersistenceException,也就是orderMapper.delOrder(2);这一句调用的时候报错,这是因为这句中我们有两个sql语句。
应该在mybatis的配置文件连接数据库的url属性中加入:&allowMultiQueries=true就可以执行多条sql语句。
再次测试:OK。
Mybatis的一对多、多对一、多对多案例相关推荐
- MyBatis→SqlSession、sqlMapConfig.xml、映射XML文件、OGNL、拼接SQL标签、取值查值、批量SQL、一对多多对一多对多
官网 https://mybatis.org/mybatis-3/ SqlSession sqlMapConfig.xml OGNL XML拼接SQL标签 参数取值 预编译与直接赋值 编码规范 sel ...
- MyBatis框架(二):多对一查询、一对多查询、ResultMap、动态SQL
在mybatis框架下写代码的步骤: 创建实体类 创建对应的接口 写每个接口对应的xml文件 编写测试类 在一对多查询和多对一查询之前,先准备数据库 以老师和学生为例 老师的数据库 CREATE TA ...
- MySQL----表的一对多关系和多对多关系
MySQL----表的一对多关系和多对多关系 1.一对多关系 1.1名词解释: 一对多关系:通过主键外关系,形成一对多关系. 一表:又称之为主表,主表需要提供主键. 多表:又称之为从表,从表需提供外键 ...
- Mybatis Plus一对多完整版实战教学!
Mybatis Plus完整版一对多实战教学! 最近做项目用到了mybatis plus 刚使用确实不是很熟练. 增删改查非常方便,但是然项目中需要用到了一对多的一个查询,我却毫无思路,所以在网上查阅 ...
- Mybatis【一对多、多对一、多对多】知识要点
Mybatis[多表连接] 我们在学习Hibernate的时候,如果表涉及到两张的话,那么我们是在映射文件中使用<set>..<many-to-one>等标签将其的映射属性关联 ...
- Mybatis入门---一对多、多对多
前几天自己配置了Mybatis的高级查询:一对多和多对多,现在记录一下,方便以后用到的时候再回顾,下面是具体的操作步骤 一.首先就是配置Mybatis的xml文件及mapper的xml文件,在这里就不 ...
- mybatis的一对多和多对多查询
一对多和多对多的关系 我是以你平时买东西为例子的,一个用户对应多个订单,一个订单对应多个订单明细,一个订单明细对应一个商品,根据这些关系来进行实例演示. 实例演示 一对多(一个订单对应多个订单明细) ...
- mybatis 一对一、一对多查询、多对多(使用注解)
1.创建数据库表 职员表: 岗位信息表: 2.创建对应实体类 岗位实体类 package com.hzsh.eomc.common.zhch.nyglgwsb.entity;import java.u ...
- mybatis学习5复杂查询之多对一的处理
前言 众所周知,一个班主任有很多学生,而每个学生只有一个班主任.那么像这种情况出现在数据库里需要怎么处理呢,本文就介绍该如何处理这种复杂查询的情况:这种情况大致分为多对一和一对多两种类型,今天我们就先 ...
最新文章
- 全面解析YOLO V4网络结构(附代码讲解)
- mysql 配置32g内存_MySQL性能测试 : 新的InnoDB Double Write Buffer
- axios取消功能的设计与实现
- Python 异步操作文件 aiofiles
- jenkins配置ant
- android怎么做版本检测,android 实现检测版本,下载apk更新(附源码)
- python蓝桥杯跑步训练
- 又一个国内知名论坛,突然被全面叫停!
- 毕设题目:Matlab通信
- 简单控制台项目:电影购票系统
- greenplum常用函数
- java中榨汁机的代码_《榨汁机食谱大全》(不断更新中)
- windows 下vscode coderunner+bash 编程
- hl uoj1841 走格子
- pe服务器注册表,在PE里如何修改系统注册表?U盘PE下修改本机注册表方法
- 原创 | 使用JUnit、AssertJ和Mockito编写单元测试和实践TDD (六)测试哪些内容:Right-BICEP
- 小程序报错类—— thirdScriptError sdk uncaught third Error Cannot read property '$mount' of unde
- 浅谈因子分析(Factor Analysis)
- cocos2d-x 流星划过特效
- java手动注册filter,SpringBoot注册Filter的两种实现方式
热门文章
- python词云自制壁纸
- java swing飞机大战游戏(源码+视频+文档+ppt)
- Futter组件整理汇总
- “华为杯”研究生数学建模竞赛2020年-【华为杯】A题:ASIC 芯片上的载波恢复 DSP 算法设计与实现(附获奖论文及matlab代码实现)
- .NetCore中EFCore for MySql
- css实现圆形白底头像框
- SAP中工艺路线删除后无法释放组计数器的问题实例
- 模糊数学(二):隶属函数的确定
- C++OpenCV下绘制灰度直方图
- 这些天的生活挺无聊的!