Mybatis多表连接(完整版)

Mybatis多表连接

    此博文主要是记录自己日常学习以及讲述给学弟的随堂笔记,故你可能会看不到完整的代码,考虑到你也兴趣,文章末尾会附上本文完整的业务需求代码素材,建议你先看末尾,再来看前文。
    转载请附上原文链接。             
                                                                   河南济源普普通通的追梦孩
                                                                           ——爱猫狗的小郝
                                                                             2020/05/06

前言

两种类型

resultType和resultMap都可以完成输出映射:

  • resultType映射要求sql查询的列名和输出映射pojo类型的属性名一致(不一致可以通过起别名来解决)
  • resultMap映射时对sql查询的列名和输出映射pojo类型的属性名作一个对应关系。(不一致也无所谓)
resultType :直接表示返回类型
基本数据类型
复杂数据类型
resultMap :对外部resultMap的引用
应用场景:
数据库字段信息与对象属性不一致
复杂的联合查询,自由控制映射结果
二者不能同时存在,本质上都是Map数据结构

resultMap

解决列名与实体类属性名不一致的问题,同时解决多表连接的查询问题。

操作步骤
  • 分析需求(主查询表、关联查询表)
  • 编写sql语句
  • resultMap进行映射的思路,在相应的pojo里加关联
  • 编写NewsMapper.xml
  • 编写NewsMapperr.java
  • 单元测试
  • 前端界面展示

association多对一

resultMap的配置

 <resultMap id="newsResultMap" type="hsy.cool.bean.News">
        <result property="id" column="id"/>
        <result property="title" column="title"/>
        <result property="content" column="content"/>
        <result property="users_id" column="users_id"/>
        <result property="category_id" column="category_id"/>
        <result property="pubtime" column="pubtime"/>
        <result property="keywords" column="keywords"/>
        <result property="state" column="state"/>
        <result property="check_users_id" column="check_users_id"/>
        <result property="check_time" column="check_time"/>
        <result property="is_elite" column="is_elite"/>
    resultMap>

查询

 <select id="findAllNor" resultMap="newsResultMap">
       select * from n_news
    select>

java代码

 List<News>findAllNor();

单元测试

@Test
    public void findAllNor(){
        NewsMapper dao= MybatisUtils.getMapper(NewsMapper.class);
        List<News> list=dao.findAllNor();
        Assert.assertNotNull(list);
        Assert.assertEquals(8,list.size());
        String time= DateUtils.parse(list.get(0).getCheck_time());
        Assert.assertEquals("2020-04-10 11:41:40",time);
    }

多表连接——简单

通过增加简单类型的属性实现展⽰多表数据的⽬的

resultMap新增

 <result property="usersName" column="nickname"/>
 <result property="categoryName" column="name"/>
 <result property="checkUsersName" column="nickname"/>

实体类新增属性

    private String usersName;
    private String categoryName;
    private String checkUsersName;
    // setter/getter

单元测试新增

 Assert.assertEquals("匿名",list.get(0).getUsersName());

多表连接——复杂

通过在实体类中添加对象的类型的属性以及assocation标签实现对复杂数据类型的映射

    <resultMap id="newsMapComplex" type="hsy.cool.bean.News">
        <result property="id" column="id"/>
        <result property="title" column="title"/>
        <result property="content" column="content"/>
        <result property="users_id" column="users_id"/>
        <result property="category_id" column="category_id"/>
        <result property="pubtime" column="pubtime"/>
        <result property="keywords" column="keywords"/>
        <result property="state" column="state"/>
        <result property="check_users_id" column="check_users_id"/>
        <result property="check_time" column="check_time"/>
        <result property="is_elite" column="is_elite"/>
        <result property="categoryName" column="name"/>
        <result property="checkUsersName" column="nickname"/>
        <association property="own" javaType="hsy.cool.bean.Users">
            <result property="id" column="id"/>
            <result property="nickname" column="nickname"/>
            <result property="realname" column="realname"/>
            <result property="phone" column="phone"/>
            <result property="email" column="email"/>
            <result property="address" column="address"/>
            <result property="createTime" column="create_time"/>
        association>
    resultMap>

查询

 <select id="findAllComplex" resultMap="newsMapComplex">
       select
         n.id,
         title,
         content,
         users_id,
         category_id,
         c.name,
         pubtime,
         keywords,
         state,
         check_users_id,
         u1.nickname,
         check_time,
         is_elite,
         u.*
        from n_news n inner join n_users u on n.users_id=u.id
                       inner join n_category c on n.category_id=c.id
                       inner join n_users u1 on n.check_users_id=u1.id
    select>

java代码

  List<News>findAllComplex();

实体类新增

  private Users own;
  //setter/getter

单元测试

    @Test
    public void  findAllComplex(){
        NewsMapper dao=MybatisUtils.getMapper(NewsMapper.class);
        List<News> list=dao.findAllComplex();
        Assert.assertNotNull(list);
        Assert.assertEquals(8,list.size());
        String time= DateUtils.parse(list.get(0).getCheck_time());
        Assert.assertEquals("2020-04-10 11:41:40",time);
        Assert.assertEquals("匿名啊啊啊",list.get(0).getOwn().getNickname());
    }

JSP页面修改

          ${news.own.nickname}
              
账号: ${news.own.nickname}
姓名: ${news.own.realname}
电话: ${news.own.phone}
邮件: ${news.own.email}
地址: ${news.own.address}

java代码修改

List<News> list=newsDao.findAllComplex();

添加样式

    

样式修改

    

导入jquery

    <script type="text/javascript" src="${pageContext.request.contextPath}/js/jquery-1.8.3.min.js">
    </script>

动态样式

    <script>
        //选择器.动作
        $(function(){
            $(".users").hover(function(){
                $(".usersInfo",this).css("display","block");
            },function(){
                $(".usersInfo",this).css("display","none");
            });
        });
    </script>

完整页面

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>


    新闻列表
    
    
    


首页/新闻

新闻列表

编号 标题 内容 分类 作者 关键字 发布时间 审批
${news.id} ${news.title} ${news.content} ${news.categoryName} ${news.own.nickname}
账号: ${news.own.nickname}
姓名: ${news.own.realname}
电话: ${news.own.phone}
邮件: ${news.own.email}
地址: ${news.own.address}
${news.keywords} ${news.pubtimeString} ${news.checkUsersName}

collection一对多

假定需要在查询新闻的同时,查询最新的两条评论。此时⽤到resultMap的collection⼦标签,它可以实现1:n的 映射。

在News类中添加属性

private List<Replys> replys;
//setter/getter

配置文件

    <resultMap id="newsMapComplexss" type="hsy.cool.bean.News">
        <result property="id" column="id"/>
        <result property="title" column="title"/>
        <result property="content" column="content"/>
        <result property="users_id" column="users_id"/>
        <result property="category_id" column="category_id"/>
        <result property="pubtime" column="pubtime"/>
        <result property="keywords" column="keywords"/>
        <result property="state" column="state"/>
        <result property="check_users_id" column="check_users_id"/>
        <result property="check_time" column="check_time"/>
        <result property="is_elite" column="is_elite"/>
        <result property="categoryName" column="name"/>
        <result property="checkUsersName" column="nickname"/>
        <association property="own" javaType="hsy.cool.bean.Users">
            <result property="id" column="id"/>
            <result property="nickname" column="nickname"/>
            <result property="realname" column="realname"/>
            <result property="phone" column="phone"/>
            <result property="email" column="email"/>
            <result property="address" column="address"/>
            <result property="createTime" column="create_time"/>
        association>
        <collection property="replys" ofType="hsy.cool.bean.Replys">
            <result property="id" column="id"/>
            <result property="new_id" column="new_id"/>
            <result property="content" column="content"/>
            <result property="users_id" column="users_id"/>
            <result property="createTime" column="create_time"/>
        collection>
    resultMap>

查询

<select id="findNewsWithReplys" parameterType="int" resultMap="newsMapComplexss">
     select
          n.id,
          n.title,
          n.content,
          n.users_id,
          n.category_id,
          n.check_time,
          n.is_elite,
          n.pubtime,
          n.keywords,
          n.state,
          n.check_users_id,
          c.name,
          u1.nickname,
          u.id,
          u.nickname,
          u.realname,
          u.phone,
          u.email,
          u.address,
          u.create_time,
          r.id,
          r.content,
          r.users_id,
          r.news_id,
          r.create_time
        from n_news n inner join n_users u on n.users_id=u.id
                       inner join n_category c on n.category_id=c.id
                       inner join n_users u1 on n.check_users_id=u1.id
                        LEFT JOIN n_replys r on r.news_id=n.id
                         WHERE n.id=#{id}
          ORDER BY r.id DESC
          LIMIT 2
    select>

NewsMapper中新增⽅法

News findNewsWithReplys(int id);

单元测试

    @Test
    public void findNewsWithReplys(){
        NewsMapper dao=MybatisUtils.getMapper(NewsMapper.class);
        News news=dao.findNewsWithReplys(7);
        Assert.assertNotNull(news);
    }

问题:我们这样写有问题没?思考

断点调试

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6S6QEw1m-1588769476174)(C:\Users\ASUS\AppData\Roaming\Typora\typora-user-images\1588737042577.png)]

分析

id这个字段在新闻表用户表评论表都有,重名问题!,同样的还有create_time/content等等字段。

解决

对配置文件进行改写,最终版配置文件

  <resultMap id="newsMapComplexss" type="hsy.cool.bean.News">
        <result property="id" column="id"/>
        <result property="title" column="title"/>
        <result property="content" column="content"/>
        <result property="users_id" column="users_id"/>
        <result property="category_id" column="category_id"/>
        <result property="pubtime" column="pubtime"/>
        <result property="keywords" column="keywords"/>
        <result property="state" column="state"/>
        <result property="check_users_id" column="check_users_id"/>
        <result property="check_time" column="check_time"/>
        <result property="is_elite" column="is_elite"/>
        <result property="categoryName" column="name"/>
        <result property="checkUsersName" column="nickname"/>
        <association property="own" javaType="hsy.cool.bean.Users">
            <result property="id" column="u_id"/>
            <result property="nickname" column="nickname"/>
            <result property="realname" column="realname"/>
            <result property="phone" column="phone"/>
            <result property="email" column="email"/>
            <result property="address" column="address"/>
            <result property="createTime" column="u_create_time"/>
        association>
        <collection property="replys" ofType="hsy.cool.bean.Replys">
            <result property="id" column="r_id"/>
            <result property="new_id" column="new_id"/>
            <result property="content" column="r_content"/>
            <result property="users_id" column="r_users_id"/>
            <result property="createTime" column="r_create_time"/>
        collection>
    resultMap>
    <select id="findNewsWithReplys" parameterType="int" resultMap="newsMapComplexss">
       select
          n.id,
          n.title,
          n.content,
          n.users_id,
          n.category_id,
          n.check_time,
          n.is_elite,
          n.pubtime,
          n.keywords,
          n.state,
          n.check_users_id,
          c.name,

          u1.nickname,

          u.id u_id,
          u.nickname,
          u.realname,
          u.phone,
          u.email,
          u.address,
          u.create_time u_create_time,
          r.id r_id,
          r.content r_content,
          r.users_id r_users_id,
          r.news_id,
          r.create_time r_create_time
          from n_news n inner join n_users u on n.users_id=u.id
                       inner join n_category c on n.category_id=c.id
                       inner join n_users u1 on n.check_users_id=u1.id
                       LEFT JOIN n_replys r on r.news_id=n.id
          WHERE n.id=7
          ORDER BY r.id DESC
          LIMIT 2

    select>

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AiTB4osi-1588769476176)(C:\Users\ASUS\AppData\Roaming\Typora\typora-user-images\1588738357976.png)]

修改list.jsp


    ${news.id}

NewsServelt

package hsy.cool.web;

import hsy.cool.bean.News;
import hsy.cool.dao.NewsMapper;
import hsy.cool.util.MybatisUtils;
import hsy.cool.util.StringUtil;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;

@WebServlet(urlPatterns="/list",name="NewsServelt")
public class NewsServelt extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //获得请求参数
        String op=req.getParameter("op");
        if("list".equals(op)){
            list(req,resp);
        }else if("find".equals(op)){
            find(req,resp);
        }else {
            throw new ServletException("不支持的操作!");
        }
        req.setCharacterEncoding("utf-8");

    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        super.doPost(req, resp);
    }
    private  void list(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        NewsMapper newsDao= MybatisUtils.getMapper(NewsMapper.class);
        List<News> list=newsDao.findAllComplex();
        req.setAttribute("list",list);
        req.getRequestDispatcher("/news/list.jsp").forward(req,resp);
    }
    private void find(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        NewsMapper newDao=MybatisUtils.getMapper(NewsMapper.class);
        int intId= StringUtil.getInt(req,"id");
        News news=newDao.findNewsWithReplys(intId);
        req.setAttribute("news",news);
        req.getRequestDispatcher("/news/detail.jsp").forward(req,resp);
    }
}

StringUtil工具类增加一个方法

    public static int getInt(HttpServletRequest req, String name) {
        String value=req.getParameter(name);
        try {
            int intValue=Integer.parseInt(value);
            return intValue;
        }catch (Exception e){

        }
        return -1;

    }

detail.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

  
    新闻内容

  
  
  

首页/新闻/内容

${news.title}

关键字:${news.keywords},作者:${news.own.nickname}.发布时间:${news.pubtimeString}

${news.content}

评论

  • ${reply.users_id}   ${reply.content} - ${reply.createTimeString}

index.jsp页面修改

   
  • 新闻
  • 业务素材

    数据库表

    /*
     Navicat Premium Data Transfer
    
     Source Server         : localhost
     Source Server Type    : MySQL
     Source Server Version : 80016
     Source Host           : localhost:3306
     Source Schema         : news
    
     Target Server Type    : MySQL
     Target Server Version : 80016
     File Encoding         : 65001
    
     Date: 21/02/2020 16:56:04
    */
    
    SET NAMES utf8mb4;
    SET FOREIGN_KEY_CHECKS = 0;
    
    -- ----------------------------
    -- Table structure for n_access_logs
    -- ----------------------------
    DROP TABLE IF EXISTS `n_access_logs`;
    CREATE TABLE `n_access_logs`  (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `ip` varchar(50) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL,
      `intime` datetime(0) DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP(0),
      `news_id` int(11) DEFAULT NULL,
      `users_id` int(11) DEFAULT NULL,
      PRIMARY KEY (`id`) USING BTREE
    ) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_bin ROW_FORMAT = Dynamic;
    
    -- ----------------------------
    -- Table structure for n_category
    -- ----------------------------
    DROP TABLE IF EXISTS `n_category`;
    CREATE TABLE `n_category`  (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `name` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL,
      PRIMARY KEY (`id`) USING BTREE
    ) ENGINE = InnoDB AUTO_INCREMENT = 7 CHARACTER SET = utf8 COLLATE = utf8_bin ROW_FORMAT = Dynamic;
    
    -- ----------------------------
    -- Records of n_category
    -- ----------------------------
    INSERT INTO `n_category` VALUES (1, '时事');
    INSERT INTO `n_category` VALUES (2, '财经');
    INSERT INTO `n_category` VALUES (3, '体育');
    INSERT INTO `n_category` VALUES (4, '娱乐');
    INSERT INTO `n_category` VALUES (5, '科技');
    INSERT INTO `n_category` VALUES (6, '旅游');
    
    -- ----------------------------
    -- Table structure for n_news
    -- ----------------------------
    DROP TABLE IF EXISTS `n_news`;
    CREATE TABLE `n_news`  (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `title` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL,
      `content` text CHARACTER SET utf8 COLLATE utf8_bin,
      `users_id` int(11) DEFAULT NULL,
      `category_id` int(11) DEFAULT NULL,
      `pubtime` datetime(0) DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP(0),
      `keywords` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL,
      `state` int(11) DEFAULT NULL COMMENT '1=新建,2=审批,3=删除',
      `check_users_id` int(11) DEFAULT NULL,
      `check_time` datetime(0) DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP(0),
      `is_elite` int(11) DEFAULT NULL COMMENT '1=精华,0=非精华',
      PRIMARY KEY (`id`) USING BTREE
    ) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_bin ROW_FORMAT = Dynamic;
    
    -- ----------------------------
    -- Table structure for n_replys
    -- ----------------------------
    DROP TABLE IF EXISTS `n_replys`;
    CREATE TABLE `n_replys`  (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `news_id` int(11) DEFAULT NULL,
      `content` varchar(1024) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL,
      `users_id` int(11) DEFAULT NULL,
      `replys_id` int(11) DEFAULT NULL,
      PRIMARY KEY (`id`) USING BTREE
    ) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_bin ROW_FORMAT = Dynamic;
    
    -- ----------------------------
    -- Table structure for n_short_replys
    -- ----------------------------
    DROP TABLE IF EXISTS `n_short_replys`;
    CREATE TABLE `n_short_replys`  (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `news_id` int(11) DEFAULT NULL,
      `type` int(11) DEFAULT NULL COMMENT '1=赞,0=踩',
      `create_time` datetime(0) DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP(0),
      `users_id` int(11) DEFAULT NULL,
      PRIMARY KEY (`id`) USING BTREE
    ) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_bin ROW_FORMAT = Dynamic;
    
    -- ----------------------------
    -- Table structure for n_users
    -- ----------------------------
    DROP TABLE IF EXISTS `n_users`;
    CREATE TABLE `n_users`  (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `nickname` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
      `realname` varchar(50) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL,
      `pwd` varchar(50) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL,
      `phone` varchar(20) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL,
      `email` varchar(100) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL,
      `address` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL,
      `create_time` datetime(0) DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP(0),
      `type` int(11) DEFAULT NULL COMMENT '0=管理员,1=读者,2=编辑',
      `realid` varchar(20) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL COMMENT '身份证号',
      PRIMARY KEY (`id`) USING BTREE
    ) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8 COLLATE = utf8_bin ROW_FORMAT = Dynamic;
    
    -- ----------------------------
    -- Records of n_users
    -- ----------------------------
    INSERT INTO `n_users` VALUES (1, '管理员', NULL, '123', NULL, NULL, NULL, '2019-10-09 10:06:39', 0, NULL);
    INSERT INTO `n_users` VALUES (2, '匿名', NULL, '123', NULL, NULL, NULL, '2019-10-09 10:11:42', 1, NULL);
    
    -- ----------------------------
    -- Table structure for student
    -- ----------------------------
    DROP TABLE IF EXISTS `student`;
    CREATE TABLE `student`  (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `name` varchar(50) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
      `phone` varchar(20) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL,
      PRIMARY KEY (`id`) USING BTREE
    ) ENGINE = InnoDB AUTO_INCREMENT = 23 CHARACTER SET = utf8 COLLATE = utf8_bin ROW_FORMAT = Dynamic;
    
    -- ----------------------------
    -- Records of student
    -- ----------------------------
    INSERT INTO `student` VALUES (1, '张三', '110');
    INSERT INTO `student` VALUES (2, '李四', '120');
    INSERT INTO `student` VALUES (3, '王五', '119');
    INSERT INTO `student` VALUES (4, '赵六', '110');
    INSERT INTO `student` VALUES (15, 'xxx', '111');
    INSERT INTO `student` VALUES (16, 'xxx', '111');
    INSERT INTO `student` VALUES (17, 'xxx', '111');
    INSERT INTO `student` VALUES (18, 'xxx', '111');
    INSERT INTO `student` VALUES (19, 'xxx', '111');
    INSERT INTO `student` VALUES (20, 'xxx', '111');
    INSERT INTO `student` VALUES (21, 'xxx', '111');
    
    -- ----------------------------
    -- Table structure for users
    -- ----------------------------
    DROP TABLE IF EXISTS `users`;
    CREATE TABLE `users`  (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `name` varchar(50) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL,
      `pwd` varchar(50) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL,
      `phone` varchar(50) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL,
      `email` varchar(100) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL,
      `address` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL,
      PRIMARY KEY (`id`) USING BTREE
    ) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8 COLLATE = utf8_bin ROW_FORMAT = Dynamic;
    
    -- ----------------------------
    -- Records of users
    -- ----------------------------
    INSERT INTO `users` VALUES (1, '张三', '123', '110', '[email protected]', '洛阳');
    INSERT INTO `users` VALUES (2, '李四', '111', '110', '[email protected]', '洛阳');
    INSERT INTO `users` VALUES (3, '李四', '555', '110', '[email protected]', '洛阳');
    
    SET FOREIGN_KEY_CHECKS = 1;
    

    其它素材可以看我同系列博文,如有兴趣,请加群870299801,备注:CSDN用户。

    水平有限,文章如有错误,请各位大佬指出,避免误人子弟。

    你可能感兴趣的:(MyBatis)