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编译版本:


 
 
  1. <dependencies>
  2. <!--数据库连接驱动-->
  3. <dependency>
  4. <groupId>mysql </groupId>
  5. <artifactId>mysql-connector-java </artifactId>
  6. <version>5.1.46 </version>
  7. </dependency>
  8. <!--mybatis-->
  9. <dependency>
  10. <groupId>org.mybatis </groupId>
  11. <artifactId>mybatis </artifactId>
  12. <version>3.3.0 </version>
  13. </dependency>
  14. <dependency>
  15. <groupId>junit </groupId>
  16. <artifactId>junit </artifactId>
  17. <version>4.12 </version>
  18. </dependency>
  19. </dependencies>
  20. <!--配置编译源代码的jdk版本-->
  21. <build>
  22. <plugins>
  23. <plugin>
  24. <artifactId>maven-compiler-plugin </artifactId>
  25. <configuration>
  26. <source>1.8 </source>
  27. <target>1.8 </target>
  28. </configuration>
  29. </plugin>
  30. </plugins>
  31. </build>

3.创建和数据库表对应的pojo。


 
 
  1. 这个实体中新加了一个数据库没有的字段products,用于存放分类对应的商品集合。
  2. public class Category {
  3. private int id;
  4. private String name;
  5. private List<Product> products;
  6. public List<Product> getProducts() {
  7. return products;
  8. }
  9. public void setProducts(List<Product> products) {
  10. this.products = products;
  11. }
  12. public int getId() {
  13. return id;
  14. }
  15. public void setId(int id) {
  16. this.id = id;
  17. }
  18. public String getName() {
  19. return name;
  20. }
  21. public void setName(String name) {
  22. this.name = name;
  23. }
  24. @Override
  25. public String toString() {
  26. return "Category{" +
  27. "id=" + id +
  28. ", name='" + name + '\'' +
  29. '}';
  30. }
  31. }

这个实体目前还未加新的字段。


 
 
  1. public class Product {
  2. private int id;
  3. private String name;
  4. private float price;
  5. public int getId() {
  6. return id;
  7. }
  8. public void setId(int id) {
  9. this.id = id;
  10. }
  11. public String getName() {
  12. return name;
  13. }
  14. public void setName(String name) {
  15. this.name = name;
  16. }
  17. public float getPrice() {
  18. return price;
  19. }
  20. public void setPrice(float price) {
  21. this.price = price;
  22. }
  23. @Override
  24. public String toString() {
  25. return "Product{" +
  26. "id=" + id +
  27. ", name='" + name + '\'' +
  28. ", price=" + price +
  29. '}';
  30. }
  31. }

4.创建mybatis的配置文件。


 
 
  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <!DOCTYPE configuration
  3. PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  4. "http://mybatis.org/dtd/mybatis-3-config.dtd">
  5. <configuration>
  6. <typeAliases> <!--设置别名-->
  7. <package name="com.byh.pojo"/>
  8. </typeAliases>
  9. <!--连接数据库-->
  10. <environments default="development">
  11. <environment id="development">
  12. <transactionManager type="JDBC"/>
  13. <dataSource type="POOLED">
  14. <property name="driver" value="com.mysql.jdbc.Driver"/>
  15. <property name="url" value="jdbc:mysql://localhost:3306/dbmybatis?characterEncoding=UTF-8"/>
  16. <property name="username" value="root"/>
  17. <property name="password" value="admin"/>
  18. </dataSource>
  19. </environment>
  20. </environments>
  21. <!--扫描mapper文件-->
  22. <mappers>
  23. <mapper resource="mapper/CategoryMapper.xml"/>
  24. </mappers>
  25. </configuration>

5.创建CategoryMapper.xml。注意:namespace的值要是对应的mapper接口。


 
 
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!DOCTYPE mapper
  3. PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  4. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  5. <mapper namespace="com.byh.mapper.CategoryMapper">
  6. <resultMap type="Category" id="categoryBean">
  7. <id column="cid" property="id" />
  8. <result column="cname" property="name" />
  9. <!-- 一对多的关系 -->
  10. <!-- property: 指的是集合属性的值, ofType:指的是集合中元素的类型 -->
  11. <collection property="products" ofType="Product">
  12. <id column="pid" property="id" />
  13. <result column="pname" property="name" />
  14. <result column="price" property="price" />
  15. </collection>
  16. </resultMap>
  17. <!-- 关联查询分类和商品表
  18. 通过left join关联查询,对Category和Product表进行关联查询。
  19. 这里不是用的resultType, 而是resultMap,通过resultMap把数据取出来放在对应的对象属性里,
  20. 通过指定列名映射实体具体的字段赋值。
  21. Category的id 字段 和Product的id字段同名,Mybatis不知道谁是谁的,所以需要通过取别名cid,pid来区分。name字段同理。
  22. -->
  23. <select id="list" resultMap="categoryBean">
  24. select c.id as 'cid', c.name as 'cname',p.id as 'pid', p.name as 'pname' ,p.price
  25. from
  26. category c left join product p
  27. on
  28. c.id = p.cid
  29. </select>
  30. </mapper>

6.创建CategoryMapper.java接口。


 
 
  1. public interface CategoryMapper {
  2. List<Category> list();
  3. }

7.测试一对多关系。


 
 
  1. import com.byh.mapper.CategoryMapper;
  2. import com.byh.pojo.Category;
  3. import com.byh.pojo.Product;
  4. import org.apache.ibatis.io.Resources;
  5. import org.apache.ibatis.session.SqlSession;
  6. import org.apache.ibatis.session.SqlSessionFactory;
  7. import org.apache.ibatis.session.SqlSessionFactoryBuilder;
  8. import org.junit.Before;
  9. import org.junit.Test;
  10. import java.io.IOException;
  11. import java.io.InputStream;
  12. import java.util.List;
  13. public class Demo2 {
  14. private SqlSession session;
  15. private CategoryMapper categoryMapper;
  16. @ Before
  17. public void bef() throws IOException {
  18. //读取mybatis配置文件
  19. InputStream inputStream = Resources.getResourceAsStream( "mybatis-config.xml");
  20. //构建sqlSession的工厂
  21. SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
  22. //创建能执行映射文件中sql的sqlSession
  23. session=sessionFactory.openSession();
  24. //获得mapper
  25. categoryMapper = session.getMapper( CategoryMapper. class);
  26. }
  27. @ Test
  28. public void test(){
  29. List< Category> list = categoryMapper.list();
  30. for( Category c : list){
  31. System.out. println( c);
  32. List< Product> products = c.getProducts();
  33. for( Product product : products){
  34. System.out. println( "\t"+product);
  35. }
  36. System.out. println( "当前循环结束");
  37. }
  38. }
  39. }

二、多以一

1.接着上面的项目写,在Product.java中添加分类字段:记得都要添加get、set方法。

2.创建ProductMapper.java接口。


 
 
  1. package com.byh.mapper;
  2. import com.byh.pojo.Product;
  3. import java.util.List;
  4. public interface ProductMapper {
  5. List<Product> productList();
  6. }

3.创建对应的mapper.xml。ProductMapper.xml如下:

注意这里多对一中指定属性类型用的是javaType,跟一对多不一样。namespace中也要指定到对应的mapper接口的完整位置。


 
 
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!DOCTYPE mapper
  3. PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  4. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  5. <mapper namespace="com.byh.mapper.ProductMapper">
  6. <resultMap id="productBean" type="Product">
  7. <id column="pid" property="id"/>
  8. <result column="pname" property="name"/>
  9. <!-- 多以一 -->
  10. <!-- property: 指的是属性名称, javaType:指的是属性的类型 -->
  11. <association property="category" javaType="Category">
  12. <id column="cid" property="id"/>
  13. <result column="cname" property="name"/>
  14. </association>
  15. </resultMap>
  16. <select id="productList" resultMap="productBean">
  17. select c.id as 'cid', c.name as 'cname',p.id as 'pid', p.name as 'pname' ,p.price
  18. from
  19. category c left join product p
  20. on
  21. c.id = p.cid
  22. </select>
  23. </mapper>

4.测试:在之前的demo中添加ProductMapper。

添加测试方法:


 
 
  1. @ Test
  2. public void test02 (){
  3. List<Product> list = productMapper.productList();
  4. for(Product p : list){
  5. System.out.println(p+ "对应的分类:"+p.getCategory());
  6. }
  7. }

结果:

三、多对多

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字段,表示订单下的订单项。


 
 
  1. public class Order {
  2. private int id;
  3. private String code;
  4. //表明订单中有哪些订单项
  5. private List<OrderItem> orderItemList;
  6. public int getId() {
  7. return id;
  8. }
  9. public void setId(int id) {
  10. this.id = id;
  11. }
  12. public String getCode() {
  13. return code;
  14. }
  15. public void setCode(String code) {
  16. this.code = code;
  17. }
  18. public List<OrderItem> getOrderItemList() {
  19. return orderItemList;
  20. }
  21. public void setOrderItemList(List<OrderItem> orderItemList) {
  22. this.orderItemList = orderItemList;
  23. }
  24. }

和OrderItem.java,注意这里跟数据库中有两个字段不一样,这里用的是对应的实体。product、order。


 
 
  1. public class OrderItem {
  2. private int id;
  3. private int number;
  4. //这里添加了商品和订单,用于表明一个订单项属于中具体是哪个商品和在哪个订单中
  5. private Product product;
  6. private Order order;
  7. public int getId() {
  8. return id;
  9. }
  10. public void setId(int id) {
  11. this.id = id;
  12. }
  13. public int getNumber() {
  14. return number;
  15. }
  16. public void setNumber(int number) {
  17. this.number = number;
  18. }
  19. public Product getProduct() {
  20. return product;
  21. }
  22. public void setProduct(Product product) {
  23. this.product = product;
  24. }
  25. public Order getOrder() {
  26. return order;
  27. }
  28. public void setOrder(Order order) {
  29. this.order = order;
  30. }
  31. }

3.创建OrderMapper.xml,这里的resultMap我个人觉得绕了一点,但是理清思路也就感觉缺一不可。


 
 
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!DOCTYPE mapper
  3. PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  4. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  5. <mapper namespace="com.byh.mapper.OrderMapper">
  6. <!--这里比较绕
  7. 查询后id和code字段放在Order对象里,
  8. 然后通过一对多的<collection>标签把oiid和number放在OrderItem对象里,
  9. 最后把pid,pname,price放进Product对象里
  10. -->
  11. <resultMap id="orderBean" type="Order">
  12. <id column="oid" property="id"/>
  13. <result column="code" property="code"/>
  14. <!--这里关联订单和所属的订单项的数据 一对多 -->
  15. <collection property="orderItemList" ofType="OrderItem">
  16. <id column="oiid" property="id" />
  17. <result column="number" property="number" />
  18. <!-- 订单项和商品是多对一 -->
  19. <association property="product" javaType="Product">
  20. <id column="pid" property="id"/>
  21. <result column="pname" property="name"/>
  22. <result column="price" property="price"/>
  23. </association>
  24. </collection>
  25. </resultMap>
  26. <select id="orderList" resultMap="orderBean">
  27. select o.id 'oid',o.code, oi.id 'oiid',oi.number, p.name 'pname', p.id 'pid',p.price
  28. from `order` o
  29. left join order_item oi on o.id =oi.oid
  30. left join product p on p.id = oi.pid
  31. </select>
  32. </mapper>

4.写对应的order的接口。这里只有一个list的接口。


 
 
  1. public interface OrderMapper {
  2. List<Order> orderList();
  3. }

5.一定要记得把xml文件添加到mybatis的映射文件中,不然会报错。

.

6.测试。在demo2.java中获得ordermapper。并调用orderList方法。


 
 
  1. @ Test
  2. public void test03( ){
  3. List<Order> os = orderMapper.orderList(); //订单列表
  4. for (Order o : os) {
  5. System. out.println(o.getCode()); //所有订单编号
  6. List<OrderItem> ois= o.getOrderItemList(); //每个订单下的订单项
  7. for (OrderItem oi : ois) { //每个订单项下的商品信息
  8. System. out.println( "商品:"+oi.getProduct().getName()+ " 价格:"+oi.getProduct().getPrice()+ " 数量:"+oi.getNumber());
  9. }
  10. }
  11. }

输出结果:

接下来做添加订单项的准备工作:

1.创建OrderItemMapper.xml,加入增加和删除的查询:


 
 
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!DOCTYPE mapper
  3. PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  4. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  5. <mapper namespace="com.byh.mapper.OrderItemMapper">
  6. <insert id="addOrderItem" parameterType="OrderItem">
  7. insert into order_item values(null,#{order.id},#{product.id},#{number})
  8. </insert>
  9. <insert id="delOrderItem" parameterType="OrderItem">
  10. delete from order_item where oid = #{order.id} and pid = #{product.id}
  11. </insert>
  12. </mapper>

2.创建OrderItemMapper接口。


 
 
  1. public interface OrderItemMapper {
  2. void addOrderItem(OrderItem orderItem);
  3. void delOrderItem(OrderItem orderItem);
  4. }

3.mybatis加入配置文件。

4.OrderMapper.xml加入:


 
 
  1. < select id= "getOrder" resultMap= "orderBean">
  2. select o.id 'oid',o.code, oi.id 'oiid',oi.number, p.name 'pname', p.id 'pid',p.price
  3. from `order` o
  4. left join order_item oi on o.id =oi.oid
  5. left join product p on p.id = oi.pid
  6. where o.id= #{id}
  7. </ select>
OrderMapper接口中添加方法:
 
 

ProductMapper.xml同理:


 
 
  1. < select id= "getProduct" resultMap= "productBean">
  2. select c.id as 'cid', c.name as 'cname',p.id as 'pid', p.name as 'pname' ,p.price
  3. from
  4. category c left join product p
  5. on
  6. c.id = p.cid
  7. where p.id= #{id}
  8. </ select>

5.测试添加订单和删除订单:

引入新的mapper:

测试方法:


 
 
  1. @Test //添加订单项
  2. public void test04(){
  3. order(); //调用上面的查询所有订单的方法
  4. System.out.println( "-----------------------------添加新的订单项后----------------------------:");
  5. Product p = productMapper.getProduct( 1);
  6. Order o = orderMapper.getOrder( 2);
  7. OrderItem orderItem = new OrderItem();
  8. orderItem.setOrder(o); //设置订单项所属订单
  9. orderItem.setProduct(p); //订单项所属商品
  10. orderItem.setNumber( 1001);
  11. orderItemMapper.addOrderItem(orderItem);
  12. order();
  13. //不加这两句 添加的数据是不会应用到数据库的
  14. session.commit();
  15. session.close();
  16. }
  17. @Test
  18. public void del(){
  19. order(); //调用上面的查询所有订单的方法
  20. System.out.println( "-----------------------------删除订单项后----------------------------:");
  21. Product p = productMapper.getProduct( 1);
  22. Order o = orderMapper.getOrder( 2);
  23. OrderItem orderItem = new OrderItem();
  24. orderItem.setOrder(o); //设置订单项所属订单
  25. orderItem.setProduct(p); //订单项所属商品
  26. orderItemMapper.delOrderItem(orderItem);
  27. order();
  28. session.commit();
  29. session.close();
  30. }

最后做一个删除订单就删除对应订单下的订单项的例子:

1.OrderMapper.xml中添加:


 
 
  1. <delete id= "delOrder" parameterType= "int" >
  2. delete from order_item where oid = #{id};
  3. delete from ` order` where id= #{id};
  4. </delete>

OrderMapper接口中添加:

2.测试方法:


 
 
  1. @Test
  2. public void delOrder(){
  3. order(); //调用上面的查询所有订单的方法
  4. orderMapper.delOrder( 2);
  5. System.out.println( "------------删除订单后:订单项也删除了---------------");
  6. order(); //调用上面的查询所有订单的方法
  7. session.commit();
  8. session.close();
  9. }

报错:org.apache.ibatis.exceptions.PersistenceException,也就是orderMapper.delOrder(2);这一句调用的时候报错,这是因为这句中我们有两个sql语句。

应该在mybatis的配置文件连接数据库的url属性中加入:&amp;allowMultiQueries=true就可以执行多条sql语句。

再次测试:OK。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值