一、一对多
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编译版本:
mysql
mysql-connector-java
5.1.46
org.mybatis
mybatis
3.3.0
junit
junit
4.12
maven-compiler-plugin
1.8
3.创建和数据库表对应的pojo。
这个实体中新加了一个数据库没有的字段products,用于存放分类对应的商品集合。
public class Category {
private int id;
private String name;
private List products;
public List getProducts() {
return products;
}
public void setProducts(List 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;
}
@Override
public 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;
}
@Override
public String toString() {
return "Product{" +
"id=" + id +
", name='" + name + '\'' +
", price=" + price +
'}';
}
}
4.创建mybatis的配置文件。
5.创建CategoryMapper.xml。注意:namespace的值要是对应的mapper接口。
6.创建CategoryMapper.java接口。
public interface CategoryMapper {
List 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;
@Before
public void bef() throws IOException {
//读取mybatis配置文件
InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
//构建sqlSession的工厂
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//创建能执行映射文件中sql的sqlSession
session=sessionFactory.openSession();
//获得mapper
categoryMapper = session.getMapper(CategoryMapper.class);
}
@Test
public void test(){
List list = categoryMapper.list();
for(Category c : list){
System.out.println(c);
List 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 productList();
}
3.创建对应的mapper.xml。ProductMapper.xml如下:
注意这里多对一中指定属性类型用的是javaType,跟一对多不一样。namespace中也要指定到对应的mapper接口的完整位置。
4.测试:在之前的demo中添加ProductMapper。
添加测试方法:
@Test
public void test02(){
List 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 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 getOrderItemList() {
return orderItemList;
}
public void setOrderItemList(List 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我个人觉得绕了一点,但是理清思路也就感觉缺一不可。
4.写对应的order的接口。这里只有一个list的接口。
public interface OrderMapper {
List orderList();
}
5.一定要记得把xml文件添加到mybatis的映射文件中,不然会报错。
6.测试。在demo2.java中获得ordermapper。并调用orderList方法。
@Test
public void test03(){
List os = orderMapper.orderList();//订单列表
for (Order o : os) {
System.out.println(o.getCode());//所有订单编号
List ois= o.getOrderItemList();//每个订单下的订单项
for (OrderItem oi : ois) {//每个订单项下的商品信息
System.out.println("商品:"+oi.getProduct().getName()+" 价格:"+oi.getProduct().getPrice()+" 数量:"+oi.getNumber());
}
}
}
输出结果:
接下来做添加订单项的准备工作:
1.创建OrderItemMapper.xml,加入增加和删除的查询:
insert into order_item values(null,#{order.id},#{product.id},#{number})
delete from order_item where oid = #{order.id} and pid = #{product.id}
2.创建OrderItemMapper接口。
public interface OrderItemMapper {
void addOrderItem(OrderItem orderItem);
void delOrderItem(OrderItem orderItem);
}
3.mybatis加入配置文件。
4.OrderMapper.xml加入:
OrderMapper接口中添加方法:
ProductMapper.xml同理:
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 from order_item where oid = #{id};
delete from `order` where id= #{id};
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。