学习目的:专栏的前两节学习中,学会使用一对多以及多对一查询,本节学习使用多对多查询。

一个订单(Order)可能有多种不同的商品(Product),一种商品可以存在于不同的订单中,而每一个产品的订单项(OrderItem),只能有一种商品的详细购买情况(id、name等)以及所属的订单(Order)。

例如:在淘宝购买东西,在同一家店里,第一次:一次性买了鞋和帽子,第二次:一次性买了鞋和裤子,这里的第一二次就是Order,鞋、帽子、裤子就是Product,每一次买的每一种Product的详细情况就是一个OrderItem(包括买了多少件、一共多少钱等)。

综上:一个订单有多种商品,一种商品可以存在于多个订单,这里就有了一对多对多(OrderItem只是维持Product和Order多对多的一个中间项)。

基于此,开始本节课程的学习。

Part 1

准备数据

新建表

create table order_ (
  id int(11) NOT NULL AUTO_INCREMENT,
  code varchar(32) DEFAULT NULL,
  PRIMARY KEY (id)
) ENGINE=MyISAM AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
 
create table order_item_(
  id int(11) NOT NULL AUTO_INCREMENT, 
  oid int ,
  pid int ,
  number int ,
  PRIMARY KEY(id)
)AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

插入数据

INSERT INTO order_ VALUES (1,'code000A');
INSERT INTO order_ VALUES (2,'code000B');
 
INSERT INTO order_item_ VALUES (null, 1, 1, 100);
INSERT INTO order_item_ VALUES (null, 1, 2, 100);
INSERT INTO order_item_ VALUES (null, 1, 3, 100);
INSERT INTO order_item_ VALUES (null, 2, 2, 100);
INSERT INTO order_item_ VALUES (null, 2, 3, 100);
INSERT INTO order_item_ VALUES (null, 2, 4, 100);

Part 2

新建实体类:Order和OrderItem。

Order

package cn.vaefun.pojo;

import java.util.List;

public class Order {
    private int id;
    private String code;

    List<OrderItem> orderItems;

    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> getOrderItems() {
        return orderItems;
    }

    public void setOrderItems(List<OrderItem> orderItems) {
        this.orderItems = orderItems;
    }
}

OrderItem

package cn.vaefun.pojo;

public class OrderItem {
    private int id;
    private int number;
    private Order order;
    private Product product;

    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 Order getOrder() {
        return order;
    }

    public void setOrder(Order order) {
        this.order = order;
    }

    public Product getProduct() {
        return product;
    }

    public void setProduct(Product product) {
        this.product = product;
    }
}

Part 3

配置xml,在pojo包中新建两个配置文件:Order.xml和OrderItem.xml。

Order.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="cn.vaefun.pojo">
    <resultMap id="orderBean" type="Order">
        <id column="oid" property="id"/>
        <result column="code" property="code"/>

        <collection property="orderItems" 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="listOrder" resultMap="orderBean">
        select o.*,p.*,oi.*, o.id 'oid', p.id 'pid', oi.id 'oiid', p.name 'pname'
                from order_ o
                left join order_item_ oi    on o.id =oi.oid
                left join product_ p on p.id = oi.pid
    </select>
    <select id="getOrder" resultMap="orderBean">
        select o.*,p.*,oi.*, o.id 'oid', p.id 'pid', oi.id 'oiid', p.name 'pname'
        from order_ o
                 left join order_item_ oi on o.id =oi.oid
                 left join product_ p on p.id = oi.pid
        where o.id = #{id}
    </select>
</mapper>

OrderItem.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="cn.vaefun.pojo">

    <insert id="addOrderItem" parameterType="OrderItem">
            insert into order_item_
                values(null,#{order.id},#{product.id},#{number})
        </insert>
    <insert id="deleteOrderItem" parameterType="OrderItem">
            delete from order_item_
                where oid = #{order.id} and pid = #{product.id}
        </insert>

</mapper>

此后,在mybatis-config.xm中映射相关配置。

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <typeAliases>
        <package name="cn.vaefun.pojo"/>
        <!--    扫描该包下的类
            使得在后续配置文件pojo.xml中使用resultType的时候,可以直接使用Category,
            而不必写全cn.vaefun.pojo.Category-->
    </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/vaefun_mybatis?characterEncoding=UTF-8"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="cn/vaefun/pojo/pojo.xml"/>
        <mapper resource="cn/vaefun/pojo/Product.xml"/>
        <mapper resource="cn/vaefun/pojo/Order.xml"/>
        <mapper resource="cn/vaefun/pojo/OrderItem.xml"/>
        <!--    映射pojo.xml    -->
    </mappers>
</configuration>

Part 4

查询操作

通过Order.xml的listOrder对应的sql语句进行查询,联合order_, order_item_, product_ 三张表进行查询:

<select id="listOrder" resultMap="orderBean">
        select o.*,p.*,oi.*, o.id 'oid', p.id 'pid', oi.id 'oiid', p.name 'pname'
                from order_ o
                left join order_item_ oi    on o.id =oi.oid
                left join product_ p on p.id = oi.pid
    </select>

查询结果 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="orderItems" 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>

测试代码块:

/**
     * 多对多查询
     * @param session
     */
    public static void listOrder(SqlSession session){
        List<Order> orders = session.selectList("listOrder");
        for (Order order : orders) {
            System.out.println(order.getCode());
            List<OrderItem> orderItems = order.getOrderItems();
            for (OrderItem orderItem : orderItems) {
                System.out.format("\t%s\t%f\t%d%n",orderItem.getProduct().getName(),
                        orderItem.getProduct().getPrice(),orderItem.getNumber());
            }
        }
    }

测试结果:

java如何处理token_java

listOrder测试结果

Part 5

建立关系:让订单000A和产品z建立了关系。

首先通过id分别获取Order对象和Product对象,然后创建一个新的OrderItem对象,接着设置Order,设置Product,设置数量,最后调用"addOrderItem" 对应的sql语句插入数据。

测试代码:

/**
     * 添加一个OrderItem
     * @param session
     */
    public static void addOrederItem(SqlSession session){
        Order order = session.selectOne("getOrder",1);
        Product product = session.selectOne("getProduct",6);
        OrderItem orderItem = new OrderItem();
        orderItem.setProduct(product);
        orderItem.setOrder(order);
        orderItem.setNumber(109);
        session.insert("addOrderItem",orderItem);
    }

测试结果:


java如何处理token_java如何处理token_02

addOrederItem测试结果

Part 6

删除了订单00A和产品z的关系,再次查询,就看不到产品z了。

删除关系的时候,通过订单id(1)和产品id(6)进行删除。

其实所谓的删除关系,就是删除掉OrderItem记录。

测试代码:

/**
     * 删除OrderItem
     * @param session
     */
    public static void deleteOrderItem(SqlSession session){
        Order order = session.selectOne("getOrder",1);
        Product product = session.selectOne("getProduct",6);
        OrderItem orderItem = new OrderItem();
        orderItem.setOrder(order);
        orderItem.setProduct(product);
        session.delete("deleteOrderItem",orderItem);
    }

测试结果:


java如何处理token_数据库_03