Mybatis的一对多、多对一、多对多关系详解(案例)

为什么需要关联关系?

在实际世界中,我们的单一实体不可能与其他实体毫无关系,事实上每个个体之间都有千丝万缕的联系。而在程序设计中就必须要考虑实体之间的关联,我们通过数据库表与表之间的链接来体现这种关联关系,比如外键引用等,而多对多是比较复杂的情况,也是最能体现现实业务逻辑的一种情况,数据库没办法直接体现多对多的关联关系,所以我们设计两个表的中间表来替代这种复杂的引用,这就是现今普遍的解决方案。

一对多和多对一

现在我有两个表,客户表(t_customer)和订单表(t_order),订单表保存了客户表的外键引用,通过外键可以表示一对多和多对一的映射关系,文末将会提供sql脚本代码,可以直接通过左侧索引跳转。

1) 实体类映射

package com.star.model;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.List;

@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class Customer {
    private Integer customerId;

    private String customerName;
    //实体层面的一对多映射
    private List<Order> orders;
}
Customer
package com.star.model;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class Order {
    private Integer orderId;

    private String orderNo;

    private Integer cid;

    //建立实体层面的映射关系
    private Customer customer;


}
Order

2)mapper映射

接口代码:

package com.star.mapper;

import com.star.model.Customer;
import com.star.model.Order;
import org.springframework.stereotype.Repository;

import java.util.List;

@Repository
public interface CustomerMapper {

    int deleteByPrimaryKey(Integer customerId);

    int insert(Customer record);

    int insertSelective(Customer record);

    Customer selectByPrimaryKey(Integer customerId);

    int updateByPrimaryKeySelective(Customer record);

    int updateByPrimaryKey(Customer record);

    //通过客户id找到客户对应的订单
    List<Order> queryOrderByCustomer(Customer customer);

}
CustomerMapper
package com.star.mapper;

import com.star.model.Customer;
import com.star.model.Order;
import org.springframework.stereotype.Repository;

@Repository
public interface OrderMapper {
    int deleteByPrimaryKey(Integer orderId);

    int insert(Order record);

    int insertSelective(Order record);

    Order selectByPrimaryKey(Integer orderId);

    int updateByPrimaryKeySelective(Order record);

    int updateByPrimaryKey(Order record);

    /*通过订单查询用户多对一*/
    Order queryCustomerByOrder(Order order);
}
OrderMapper

xml映射:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "mybatis-3-mapper.dtd" >
<!--客户映射-->
<mapper namespace="com.star.mapper.CustomerMapper" >
  <resultMap id="BaseResultMap" type="com.star.model.Customer" >
    <constructor >
      <idArg column="customer_id" jdbcType="INTEGER" javaType="java.lang.Integer" />
      <arg column="customer_name" jdbcType="VARCHAR" javaType="java.lang.String" />
    </constructor>
  </resultMap>

  <!-- 要返回的订单结果集(一对多) -->
  <resultMap id="baseOneToMany" type="com.star.model.Customer" >
    <!--定义主键-->
    <id column="customer_id" property="customerId" javaType="java.lang.Integer"/>
    <result column="customer_name" property="customerName" javaType="java.lang.String"/>
    <!-- 一对多的关系 -->
    <!-- property: 指的是集合属性的值, ofType:指的是集合中元素的类型 -->
    <collection property="orders" ofType="com.star.model.Order">
      <id column="order_id" property="orderId"/>
      <result column="order_no" property="orderNo"/>
      <result column="cid" property="cid"/>
    </collection>
  </resultMap>

  <sql id="Base_Column_List" >
    customer_id, customer_name
  </sql>

  <sql id="base_query_list">
    select <include refid="Base_Column_List"/> from t_customer where 1=1
  </sql>

  <!--找到客户对应订单映射sql-->
  <select id="queryOrderByCustomer" resultMap="baseOneToMany">
    select * from t_customer ct left join  t_order od on ct.customer_id=od.cid where 1=1
    <if test="customerId!=null">
      and customer_id = #{customerId}
    </if>
  </select>

  <insert id="insert" parameterType="com.star.model.Customer" >
    insert into t_customer (customer_id, customer_name)
    values (#{customerId,jdbcType=INTEGER}, #{customerName,jdbcType=VARCHAR})
  </insert>
  <insert id="insertSelective" parameterType="com.star.model.Customer" >
    insert into t_customer
    <trim prefix="(" suffix=")" suffixOverrides="," >
      <if test="customerId != null" >
        customer_id,
      </if>
      <if test="customerName != null" >
        customer_name,
      </if>
    </trim>
    <trim prefix="values (" suffix=")" suffixOverrides="," >
      <if test="customerId != null" >
        #{customerId,jdbcType=INTEGER},
      </if>
      <if test="customerName != null" >
        #{customerName,jdbcType=VARCHAR},
      </if>
    </trim>
  </insert>

  <update id="updateByPrimaryKeySelective" parameterType="com.star.model.Customer" >
    update t_customer
    <set >
      <if test="customerName != null" >
        customer_name = #{customerName,jdbcType=VARCHAR},
      </if>
    </set>
    where customer_id = #{customerId,jdbcType=INTEGER}
  </update>
  <update id="updateByPrimaryKey" parameterType="com.star.model.Customer" >
    update t_customer
    set customer_name = #{customerName,jdbcType=VARCHAR}
    where customer_id = #{customerId,jdbcType=INTEGER}
  </update>
  <delete id="deleteByPrimaryKey" parameterType="java.lang.Integer" >
    delete from t_customer
    where customer_id = #{customerId,jdbcType=INTEGER}
  </delete>

  <select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="java.lang.Integer" >
    select
    <include refid="Base_Column_List" />
    from t_customer
    where customer_id = #{customerId,jdbcType=INTEGER}
  </select>
</mapper>
Customer.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.star.mapper.OrderMapper">
    <resultMap id="BaseResultMap" type="com.star.model.Order">
        <constructor>
            <idArg column="order_id" jdbcType="INTEGER" javaType="java.lang.Integer"/>
            <arg column="order_no" jdbcType="VARCHAR" javaType="java.lang.String"/>
            <arg column="cid" jdbcType="INTEGER" javaType="java.lang.Integer"/>
        </constructor>
    </resultMap>
    <!--对应关系结果集(多对一)-->
    <resultMap id="baseManyToOne" type="com.star.model.Order">
        <id column="order_id" property="orderId"/>
        <result column="order_no" property="orderNo"/>
        <result column="cid" property="cid"/>
        <!-- 多对一的关系 -->
        <!-- property: 指的是属性的值, javaType:指的是属性的类型-->
        <association property="customer" javaType="com.star.model.Customer">
            <id column="customer_id" property="customerId"/>
            <result column="customer_name" property="customerName"/>
        </association>
    </resultMap>
    <sql id="Base_Column_List">
    order_id, order_no, cid
  </sql>
    <select id="queryCustomerByOrder" resultMap="baseManyToOne">
      select  * from t_order od inner join t_customer cu on cu.customer_id=od.cid where 1=1
      and order_id = #{orderId}
  </select>
    <select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="java.lang.Integer">
        select
        <include refid="Base_Column_List"/>
        from t_order
        where order_id = #{orderId,jdbcType=INTEGER}
    </select>
    <delete id="deleteByPrimaryKey" parameterType="java.lang.Integer">
    delete from t_order
    where order_id = #{orderId,jdbcType=INTEGER}
  </delete>
    <insert id="insert" parameterType="com.star.model.Order">
    insert into t_order (order_id, order_no, cid
      )
    values (#{orderId,jdbcType=INTEGER}, #{orderNo,jdbcType=VARCHAR}, #{cid,jdbcType=INTEGER}
      )
  </insert>
    <insert id="insertSelective" parameterType="com.star.model.Order">
        insert into t_order
        <trim prefix="(" suffix=")" suffixOverrides=",">
            <if test="orderId != null">
                order_id,
            </if>
            <if test="orderNo != null">
                order_no,
            </if>
            <if test="cid != null">
                cid,
            </if>
        </trim>
        <trim prefix="values (" suffix=")" suffixOverrides=",">
            <if test="orderId != null">
                #{orderId,jdbcType=INTEGER},
            </if>
            <if test="orderNo != null">
                #{orderNo,jdbcType=VARCHAR},
            </if>
            <if test="cid != null">
                #{cid,jdbcType=INTEGER},
            </if>
        </trim>
    </insert>
    <update id="updateByPrimaryKeySelective" parameterType="com.star.model.Order">
        update t_order
        <set>
            <if test="orderNo != null">
                order_no = #{orderNo,jdbcType=VARCHAR},
            </if>
            <if test="cid != null">
                cid = #{cid,jdbcType=INTEGER},
            </if>
        </set>
        where order_id = #{orderId,jdbcType=INTEGER}
    </update>
    <update id="updateByPrimaryKey" parameterType="com.star.model.Order">
    update t_order
    set order_no = #{orderNo,jdbcType=VARCHAR},
      cid = #{cid,jdbcType=INTEGER}
    where order_id = #{orderId,jdbcType=INTEGER}
  </update>
</mapper>
Order.xml

3)junit测试

service代码我就不贴了,注意注入mapper接口就OK。

baseTest:

package com.star.service.impl;

import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import javax.annotation.Resource;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:applicationContext.xml"})
public class BaseTest {


}
View Code

测试结果:

1)测试通过客户id查询对应的订单(一对多)

2020-11-12 10:28:26.674 [main-135] DEBUG org.apache.ibatis.logging.LogFactory - Logging initialized using 'class org.apache.ibatis.logging.slf4j.Slf4jImpl' adapter.
2020-11-12 10:28:27.190 [main-109] DEBUG org.apache.ibatis.io.VFS - Class not found: org.jboss.vfs.VFS
2020-11-12 10:28:27.191 [main-142] DEBUG org.apache.ibatis.io.JBoss6VFS - JBoss 6 VFS API is not available in this environment.
2020-11-12 10:28:27.192 [main-109] DEBUG org.apache.ibatis.io.VFS - Class not found: org.jboss.vfs.VirtualFile
2020-11-12 10:28:27.193 [main-70] DEBUG org.apache.ibatis.io.VFS - VFS implementation org.apache.ibatis.io.JBoss6VFS is not valid in this environment.
2020-11-12 10:28:27.195 [main-84] DEBUG org.apache.ibatis.io.VFS - Using VFS adapter org.apache.ibatis.io.DefaultVFS
2020-11-12 10:28:29.294 [main-159] DEBUG com.star.mapper.CustomerMapper.queryOrderByCustomer - ==>  Preparing: select * from t_customer ct left join t_order od on ct.customer_id=od.cid where 1=1 and customer_id = ? 
2020-11-12 10:28:29.329 [main-159] DEBUG com.star.mapper.CustomerMapper.queryOrderByCustomer - ==> Parameters: 1(Integer)
2020-11-12 10:28:29.357 [main-165] TRACE com.star.mapper.CustomerMapper.queryOrderByCustomer - <==    Columns: customer_id, customer_name, order_id, order_no, cid
2020-11-12 10:28:29.359 [main-165] TRACE com.star.mapper.CustomerMapper.queryOrderByCustomer - <==        Row: 1, zs, 1, P01, 1
2020-11-12 10:28:29.363 [main-165] TRACE com.star.mapper.CustomerMapper.queryOrderByCustomer - <==        Row: 1, zs, 2, P02, 1
2020-11-12 10:28:29.364 [main-165] TRACE com.star.mapper.CustomerMapper.queryOrderByCustomer - <==        Row: 1, zs, 3, P03, 1
2020-11-12 10:28:29.365 [main-165] TRACE com.star.mapper.CustomerMapper.queryOrderByCustomer - <==        Row: 1, zs, 4, P04, 1
2020-11-12 10:28:29.367 [main-165] TRACE com.star.mapper.CustomerMapper.queryOrderByCustomer - <==        Row: 1, zs, 5, P05, 1
2020-11-12 10:28:29.367 [main-159] DEBUG com.star.mapper.CustomerMapper.queryOrderByCustomer - <==      Total: 5
Customer(customerId=1, customerName=zs, orders=[Order(orderId=1, orderNo=P01, cid=1, customer=null), Order(orderId=2, orderNo=P02, cid=1, customer=null), Order(orderId=3, orderNo=P03, cid=1, customer=null), Order(orderId=4, orderNo=P04, cid=1, customer=null), Order(orderId=5, orderNo=P05, cid=1, customer=null)])

2)测试通过订单id查询对应的客户(多对一)

2020-11-12 10:31:38.681 [main-135] DEBUG org.apache.ibatis.logging.LogFactory - Logging initialized using 'class org.apache.ibatis.logging.slf4j.Slf4jImpl' adapter.
2020-11-12 10:31:39.064 [main-109] DEBUG org.apache.ibatis.io.VFS - Class not found: org.jboss.vfs.VFS
2020-11-12 10:31:39.068 [main-142] DEBUG org.apache.ibatis.io.JBoss6VFS - JBoss 6 VFS API is not available in this environment.
2020-11-12 10:31:39.070 [main-109] DEBUG org.apache.ibatis.io.VFS - Class not found: org.jboss.vfs.VirtualFile
2020-11-12 10:31:39.072 [main-70] DEBUG org.apache.ibatis.io.VFS - VFS implementation org.apache.ibatis.io.JBoss6VFS is not valid in this environment.
2020-11-12 10:31:39.075 [main-84] DEBUG org.apache.ibatis.io.VFS - Using VFS adapter org.apache.ibatis.io.DefaultVFS
2020-11-12 10:31:41.563 [main-159] DEBUG com.star.mapper.OrderMapper.queryCustomerByOrder - ==>  Preparing: select * from t_order od inner join t_customer cu on cu.customer_id=od.cid where 1=1 and order_id = ? 
2020-11-12 10:31:41.601 [main-159] DEBUG com.star.mapper.OrderMapper.queryCustomerByOrder - ==> Parameters: 1(Integer)
2020-11-12 10:31:41.625 [main-165] TRACE com.star.mapper.OrderMapper.queryCustomerByOrder - <==    Columns: order_id, order_no, cid, customer_id, customer_name
2020-11-12 10:31:41.625 [main-165] TRACE com.star.mapper.OrderMapper.queryCustomerByOrder - <==        Row: 1, P01, 1, 1, zs
2020-11-12 10:31:41.628 [main-159] DEBUG com.star.mapper.OrderMapper.queryCustomerByOrder - <==      Total: 1
Order(orderId=1, orderNo=P01, cid=1, customer=Customer(customerId=1, customerName=zs, orders=null))

多对多

表结构,新闻和类型标签之间的多对多关系(一个标签可以对应多个新闻,一个新闻可以有多个标签):

-- 多对多
-- 主表
create table t_news
(
    news_id int primary key auto_increment,          -- 新闻ID:主鍵
    title varchar(50) not null                       -- 标题
);

-- 主表
create table t_category
(
    category_id int primary key auto_increment,      -- 类别编号:主鍵
    category_name varchar(50) not null               -- 类别名称
);
-- 中间表
create table t_news_category
(
    id int primary key not null auto_increment,
    nid int not null,
    cid int not null,
    foreign key(nid) references t_news(news_id),
    foreign key(cid) references t_category(category_id)
);

1)实体层

使用了lombok插件,可以快速提供无参和有参的构造函数。

package com.star.model;

import lombok.*;

import java.util.List;

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class News {
    private Integer newsId;

    private String title;

    private List<Category> categories;

    //后面会用到
    public News(Integer newsId, String title) {
        this.newsId = newsId;
        this.title = title;
    }
}
package com.star.model;


import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.List;

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Category {
    private Integer categoryId;

    private String categoryName;

    private List<News> news;

    //后面会用到
    public Category(Integer categoryId, String categoryName) {
        this.categoryId = categoryId;
        this.categoryName = categoryName;
    }
}

2)mapper层

接口代码:

package com.star.mapper;

import com.star.model.Category;
import com.star.model.News;
import org.springframework.stereotype.Repository;

import java.util.List;

@Repository
public interface NewsMapper {
    int deleteByPrimaryKey(Integer newsId);

    int insert(News record);

    int insertSelective(News record);

    News selectByPrimaryKey(Integer newsId);

    int updateByPrimaryKeySelective(News record);

    int updateByPrimaryKey(News record);

    //通过新闻id查找到新闻对应的类型标签
    News queryCategoryByNewId(News news);

}
news
package com.star.mapper;

import com.star.model.Category;
import com.star.model.News;
import org.springframework.stereotype.Repository;

import java.util.List;

@Repository
public interface CategoryMapper {
    int deleteByPrimaryKey(Integer categoryId);

    int insert(Category record);

    int insertSelective(Category record);

    Category selectByPrimaryKey(Integer categoryId);

    int updateByPrimaryKeySelective(Category record);

    int updateByPrimaryKey(Category record);

    //通过类型id找到对应的新闻集合
    Category queryNewsByCategoryId(Category category);
}
category

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.star.mapper.NewsMapper">
    <resultMap id="BaseResultMap" type="com.star.model.News">
        <constructor>
            <idArg column="news_id" jdbcType="INTEGER" javaType="java.lang.Integer"/>
            <arg column="title" jdbcType="VARCHAR" javaType="java.lang.String"/>
        </constructor>
    </resultMap>
    <!--实际也可以不用单独写出来而是包含在collection标签内,但是为了好区分-->
    <resultMap id="base_categories" type="com.star.model.Category">
        <id column="category_id" property="categoryId"/>
        <result column="category_name" property="categoryName"/>
    </resultMap>
    
    <!-- 新闻对应多个类型标签:一对多关系 -->
    <resultMap id="newsManyToMany" type="com.star.model.News" extends="BaseResultMap">
<!--        <id column="news_id" property="newsId"/>-->
<!--        <result column="title" property="title"/>-->
        <collection property="categories" resultMap="base_categories">
        </collection>
    </resultMap>
    <sql id="Base_Column_List">
    news_id, title
    </sql>
    <!--为了方便用*代替,实际开发禁用,这里的外键引用字段都是不同的,所以可以用*
        通过新闻查找类型
    -->
    <select id="queryCategoryByNewId" resultMap="newsManyToMany">
        select * from t_news nws
        left join t_news_category nct on nws.news_id = nct.nid
        left join t_category ctg on ctg.category_id = nct.cid
        where nws.news_id = #{newsId}
    </select>
    <select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="java.lang.Integer">
        select
        <include refid="Base_Column_List"/>
        from t_news
        where news_id = #{newsId,jdbcType=INTEGER}
    </select>
    <delete id="deleteByPrimaryKey" parameterType="java.lang.Integer">
    delete from t_news
    where news_id = #{newsId,jdbcType=INTEGER}
  </delete>
    <insert id="insert" parameterType="com.star.model.News">
    insert into t_news (news_id, title)
    values (#{newsId,jdbcType=INTEGER}, #{title,jdbcType=VARCHAR})
  </insert>
    <insert id="insertSelective" parameterType="com.star.model.News">
        insert into t_news
        <trim prefix="(" suffix=")" suffixOverrides=",">
            <if test="newsId != null">
                news_id,
            </if>
            <if test="title != null">
                title,
            </if>
        </trim>
        <trim prefix="values (" suffix=")" suffixOverrides=",">
            <if test="newsId != null">
                #{newsId,jdbcType=INTEGER},
            </if>
            <if test="title != null">
                #{title,jdbcType=VARCHAR},
            </if>
        </trim>
    </insert>
    <update id="updateByPrimaryKeySelective" parameterType="com.star.model.News">
        update t_news
        <set>
            <if test="title != null">
                title = #{title,jdbcType=VARCHAR},
            </if>
        </set>
        where news_id = #{newsId,jdbcType=INTEGER}
    </update>
    <update id="updateByPrimaryKey" parameterType="com.star.model.News">
    update t_news
    set title = #{title,jdbcType=VARCHAR}
    where news_id = #{newsId,jdbcType=INTEGER}
  </update>
</mapper>
news
<?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.star.mapper.CategoryMapper">
    <resultMap id="BaseResultMap" type="com.star.model.Category">
        <constructor>
            <idArg column="category_id" jdbcType="INTEGER" javaType="java.lang.Integer"/>
            <arg column="category_name" jdbcType="VARCHAR" javaType="java.lang.String"/>
        </constructor>
    </resultMap>

    <resultMap id="baseNews" type="com.star.model.News">
        <id column="news_id" property="newsId"/>
        <result column="title" property="title"/>
        <collection property="categories" resultMap="BaseResultMap"/>
    </resultMap>

  <!-- 新闻对应多个类型标签:一对多关系 -->
  <resultMap id="categoryManyToMany" type="com.star.model.Category">
    <id column="category_id" property="categoryId"/>
    <result column="category_name" property="categoryName"/>
    <collection property="news" resultMap="baseNews">
    </collection>
  </resultMap>
    <sql id="Base_Column_List">
    category_id, category_name
  </sql>
    <select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="java.lang.Integer">
        select
        <include refid="Base_Column_List"/>
        from t_category
        where category_id = #{categoryId,jdbcType=INTEGER}
    </select>
    <!--要注意的是主从关系,类型应该是主表,新闻是从表-->
    <select id="queryNewsByCategoryId" resultMap="categoryManyToMany">
        select * from t_category ctg
        left join t_news_category nct on ctg.category_id = nct.cid
        left join t_news nws on nws.news_id = nct.nid
        where ctg.category_id = #{categoryId}
    </select>
    <delete id="deleteByPrimaryKey" parameterType="java.lang.Integer">
    delete from t_category
    where category_id = #{categoryId,jdbcType=INTEGER}
  </delete>
    <insert id="insert" parameterType="com.star.model.Category">
    insert into t_category (category_id, category_name)
    values (#{categoryId,jdbcType=INTEGER}, #{categoryName,jdbcType=VARCHAR})
  </insert>
    <insert id="insertSelective" parameterType="com.star.model.Category">
        insert into t_category
        <trim prefix="(" suffix=")" suffixOverrides=",">
            <if test="categoryId != null">
                category_id,
            </if>
            <if test="categoryName != null">
                category_name,
            </if>
        </trim>
        <trim prefix="values (" suffix=")" suffixOverrides=",">
            <if test="categoryId != null">
                #{categoryId,jdbcType=INTEGER},
            </if>
            <if test="categoryName != null">
                #{categoryName,jdbcType=VARCHAR},
            </if>
        </trim>
    </insert>
    <update id="updateByPrimaryKeySelective" parameterType="com.star.model.Category">
        update t_category
        <set>
            <if test="categoryName != null">
                category_name = #{categoryName,jdbcType=VARCHAR},
            </if>
        </set>
        where category_id = #{categoryId,jdbcType=INTEGER}
    </update>
    <update id="updateByPrimaryKey" parameterType="com.star.model.Category">
    update t_category
    set category_name = #{categoryName,jdbcType=VARCHAR}
    where category_id = #{categoryId,jdbcType=INTEGER}
  </update>
</mapper>
category

3)测试

同样的我就不贴Service了,测试代码:

package com.star.service.impl;

import com.star.model.Category;
import com.star.model.News;
import com.star.service.ICategoryService;
import com.star.service.INewsService;
import org.junit.Before;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;

import static org.junit.Assert.*;

public class NewsServiceImplTest extends BaseTest{

    @Autowired
    private INewsService newsService;

    @Autowired
    private ICategoryService categoryService;

    @Test
    public void queryCategoryByNewId() {
        //测试查询新闻对应的标签类型
        System.out.println(newsService.queryCategoryByNewId(News.builder().newsId(4).build()));
        //测试标签类型对应的新闻
        System.out.println(categoryService.queryNewsByCategoryId(Category.builder().categoryId(2).build()));
    }
}

测试结果:

2020-11-12 10:51:57.725 [main-135] DEBUG org.apache.ibatis.logging.LogFactory - Logging initialized using 'class org.apache.ibatis.logging.slf4j.Slf4jImpl' adapter.
2020-11-12 10:51:58.185 [main-109] DEBUG org.apache.ibatis.io.VFS - Class not found: org.jboss.vfs.VFS
2020-11-12 10:51:58.186 [main-142] DEBUG org.apache.ibatis.io.JBoss6VFS - JBoss 6 VFS API is not available in this environment.
2020-11-12 10:51:58.189 [main-109] DEBUG org.apache.ibatis.io.VFS - Class not found: org.jboss.vfs.VirtualFile
2020-11-12 10:51:58.190 [main-70] DEBUG org.apache.ibatis.io.VFS - VFS implementation org.apache.ibatis.io.JBoss6VFS is not valid in this environment.
2020-11-12 10:51:58.192 [main-84] DEBUG org.apache.ibatis.io.VFS - Using VFS adapter org.apache.ibatis.io.DefaultVFS
2020-11-12 10:52:00.854 [main-159] DEBUG com.star.mapper.NewsMapper.queryCategoryByNewId - ==>  Preparing: select * from t_news nws left join t_news_category nct on nws.news_id = nct.nid left join t_category ctg on ctg.category_id = nct.cid where nws.news_id = ? 
2020-11-12 10:52:00.892 [main-159] DEBUG com.star.mapper.NewsMapper.queryCategoryByNewId - ==> Parameters: 4(Integer)
2020-11-12 10:52:00.919 [main-165] TRACE com.star.mapper.NewsMapper.queryCategoryByNewId - <==    Columns: news_id, title, id, nid, cid, category_id, category_name
2020-11-12 10:52:00.921 [main-165] TRACE com.star.mapper.NewsMapper.queryCategoryByNewId - <==        Row: 4, 113, 8, 4, 1, 1, 焦点
2020-11-12 10:52:00.926 [main-165] TRACE com.star.mapper.NewsMapper.queryCategoryByNewId - <==        Row: 4, 113, 9, 4, 2, 2, 国际
2020-11-12 10:52:00.927 [main-165] TRACE com.star.mapper.NewsMapper.queryCategoryByNewId - <==        Row: 4, 113, 10, 4, 3, 3, 社会
2020-11-12 10:52:00.927 [main-165] TRACE com.star.mapper.NewsMapper.queryCategoryByNewId - <==        Row: 4, 113, 11, 4, 4, 4, 房产
2020-11-12 10:52:00.929 [main-159] DEBUG com.star.mapper.NewsMapper.queryCategoryByNewId - <==      Total: 4
News(newsId=4, title=113, categories=[Category(categoryId=1, categoryName=焦点, news=null), Category(categoryId=2, categoryName=国际, news=null), Category(categoryId=3, categoryName=社会, news=null), Category(categoryId=4, categoryName=房产, news=null)])
2020-11-12 10:52:00.938 [main-159] DEBUG com.star.mapper.CategoryMapper.queryNewsByCategoryId - ==>  Preparing: select * from t_category ctg left join t_news_category nct on ctg.category_id = nct.cid left join t_news nws on nws.news_id = nct.nid where ctg.category_id = ? 
2020-11-12 10:52:00.939 [main-159] DEBUG com.star.mapper.CategoryMapper.queryNewsByCategoryId - ==> Parameters: 2(Integer)
2020-11-12 10:52:00.941 [main-165] TRACE com.star.mapper.CategoryMapper.queryNewsByCategoryId - <==    Columns: category_id, category_name, id, nid, cid, news_id, title
2020-11-12 10:52:00.941 [main-165] TRACE com.star.mapper.CategoryMapper.queryNewsByCategoryId - <==        Row: 2, 国际, 2, 1, 2, 1, 110
2020-11-12 10:52:00.943 [main-165] TRACE com.star.mapper.CategoryMapper.queryNewsByCategoryId - <==        Row: 2, 国际, 4, 2, 2, 2, 111
2020-11-12 10:52:00.944 [main-165] TRACE com.star.mapper.CategoryMapper.queryNewsByCategoryId - <==        Row: 2, 国际, 6, 3, 2, 3, 112
2020-11-12 10:52:00.945 [main-165] TRACE com.star.mapper.CategoryMapper.queryNewsByCategoryId - <==        Row: 2, 国际, 9, 4, 2, 4, 113
2020-11-12 10:52:00.946 [main-159] DEBUG com.star.mapper.CategoryMapper.queryNewsByCategoryId - <==      Total: 4
Category(categoryId=2, categoryName=国际, news=[News(newsId=1, title=110, categories=null), News(newsId=2, title=111, categories=null), News(newsId=3, title=112, categories=null), News(newsId=4, title=113, categories=null)])

可以看到已经获取到我们想要的数据。

数据库脚本

-- 一对多
-- 客户表(主表)
create table t_customer
(
    customer_id int primary key not null auto_increment,
    customer_name varchar(50) not null
);

-- 多对一
-- 订单表(从表)
create table t_order
(
    order_id int primary key not null auto_increment,
    order_no varchar(50) not null unique,
    cid int not null,
    foreign key(cid) references t_customer(customer_id)
);

-- 与mssql不一样,自动增长是可以赋值,也可以不赋值
insert into t_customer(customer_id,customer_name) values(1, 'zs');
insert into t_customer(customer_id,customer_name) values(2, 'ls');
insert into t_customer(customer_id,customer_name) values(3, 'ww');
insert into t_customer(customer_id,customer_name) values(4, 'xm');

insert into t_order(order_no,cid) values('P01',1);
insert into t_order(order_no,cid) values('P02',1);
insert into t_order(order_no,cid) values('P03',1);
insert into t_order(order_no,cid) values('P04',1);
insert into t_order(order_no,cid) values('P05',1);
insert into t_order(order_no,cid) values('P06',2);
insert into t_order(order_no,cid) values('P07',2);
insert into t_order(order_no,cid) values('P08',2);
insert into t_order(order_no,cid) values('P09',3);
insert into t_order(order_no,cid) values('P10',3);

SELECT * FROM t_customer;
SELECT * FROM t_order;
select * from t_customer ct left join  t_order od on ct.customer_id=od.cid where 1=1;


-- 多对多
-- 主表
create table t_news
(
    news_id int primary key auto_increment,          -- 新闻ID:主鍵
    title varchar(50) not null                       -- 标题
);

-- 主表
create table t_category
(
    category_id int primary key auto_increment,      -- 类别编号:主鍵
    category_name varchar(50) not null               -- 类别名称
);

-- 中间表
create table t_news_category
(
    id int primary key not null auto_increment,
    nid int not null,
    cid int not null,
    foreign key(nid) references t_news(news_id),
    foreign key(cid) references t_category(category_id)
);
insert into t_news(news_id,title) values(1,'110');
insert into t_news(news_id,title) values(2,'111');
insert into t_news(news_id,title) values(3,'112');
insert into t_news(news_id,title) values(4,'113');
insert into t_news(news_id,title) values(5,'114');
insert into t_news(news_id,title) values(6,'115');
insert into t_news(news_id,title) values(7,'116');
insert into t_news(news_id,title) values(8,'117');
insert into t_news(news_id,title) values(9,'118');


insert into t_category(category_id,category_name) values(1,'焦点');
insert into t_category(category_id,category_name) values(2,'国际');
insert into t_category(category_id,category_name) values(3,'社会');
insert into t_category(category_id,category_name) values(4,'房产');
insert into t_category(category_id,category_name) values(5,'财经');
insert into t_category(category_id,category_name) values(6,'娱乐');


insert into t_news_category(nid,cid) values(1,1);
insert into t_news_category(nid,cid) values(1,2);

insert into t_news_category(nid,cid) values(2,1);
insert into t_news_category(nid,cid) values(2,2);

insert into t_news_category(nid,cid) values(3,1);
insert into t_news_category(nid,cid) values(3,2);
insert into t_news_category(nid,cid) values(3,3);

insert into t_news_category(nid,cid) values(4,1);
insert into t_news_category(nid,cid) values(4,2);
insert into t_news_category(nid,cid) values(4,3);
insert into t_news_category(nid,cid) values(4,4);



SELECT * FROM t_news;
SELECT * FROM t_category;
SELECT * FROM t_news_category;

select *
FROM t_news nws
         LEFT JOIN t_news_category nct
                   ON nws.news_id = nct.nid
         LEFT JOIN t_category ctg
                   ON ctg.category_id = nct.cid
WHERE nws.news_id = 4;
posted @ 2020-11-12 10:57  _未来可期  阅读(498)  评论(0编辑  收藏  举报