Springboot中使用Mybatis框架对数据库进行联表查询,踩坑填坑

本文详细介绍了MyBatis中使用原生SQL进行连表查询的方法,包括内连接、外连接、交叉连接和联合连接的使用场景及SQL语句示例。特别关注了左外连接、右外连接和全外连接的区别,并提供了避免外键冲突和表名关键字冲突的解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

因为mybatis使用的基本是原生sql语句
所以首先从数据库开始说
以mysql数据库为例,对表的连接查询分为四种
内连接,外连接,交叉连接,和联合连接

内连接使用比较运算符根据每个表共有的列的值匹配两个表中的行
sql语句举例:联接查询user,order表中user的id相同的数据,前五列为user表的内容,后面的是order表。

SELECT * FROM  `user` INNER JOIN `order` ON user.id=order.userID;

在这里插入图片描述

内连接也被称为普通连接或者自然连接,内连接是从结果表中删除与其他被连接表中没有匹配行的所有行,所以内连接可能会丢失信息

外连接又分为左外连接,右外连接和全外连接

左外连接:以左表为基表(驱动表),将左表的每一条数据都与右表匹配,如果在右表中没有匹配数据,则右表补null
举例说明一下
我们把用户表当做左表,订单表为右表

SELECT * FROM  `user` LEFT JOIN `order` ON user.id=order.userID;

看一下查询结果,发现id为2的没有订单表的信息,全部用null填充了。
在这里插入图片描述
左外连接就是对左边的表不加限制,左边表的信息不会丢失

右外连接和左外连接相反,保留右表的所有信息。

SELECT * FROM  `user` RIGHT JOIN `order` ON user.id=order.userID;

全外连接就是左右信息都保留,匹配不到的用null填充。

第三种是交叉连接
它返回结果集合中的数据行数等于第一个表中符合查询条件的数据行数乘以第二个表中符合查询条件的数据行数,也叫笛卡尔积,不带where字句。

SELECT * FROM  `user`  CROSS JOIN `order`;

在这里插入图片描述

第四种是联合联接
这是一种很少见的连接方式。Oracle、MySQL均不支持,其作用是:找出全外连接和内连接之间差异的所有行。这在数据分析中排错中比较常用。也可以利用数据库的集合操作来实现此功能,这里不做展示了。

接下来说一下连表容易踩到的坑
首先是外键冲突
如果A表关联了B表,比如说我用户关联了订单表
那么在插入订单时,应该先去判断是否有这个用户
删除用户时,应该先去把他关联的订单删除,
否则就会有外键冲突。

再就是表的名字,在mysql中,如果使用了关键字作为表的名字会报语句错误,应该给表名加上``这个符号,这是横排数字按键数字1旁边的那个键在英文输入下输出的。

下面放一下在mybatis下连表查询的代码步骤。

第一步正常建表就不说了,如果忘记设置外键,说一下增加外键的语句

ALTER TABLE `order` ADD CONSTRAINT fk_user_id FOREIGN KEY (user_id) REFERENCES `user`(id)

然后是建相应的实体类,和Mapper.xml
User.java

package com.jerry.springbootdemo.entity;

import lombok.Data;

import java.util.List;
@Data
public class User {
    private Integer id;

    private String username;

    private String passsword;

    private String gender;

    private String hobby;

    private List<Order> orderList;

}

Order.java

package com.jerry.springbootdemo.entity;

import lombok.Data;

import java.math.BigDecimal;
import java.util.Date;
@Data
public class Order {
    private Integer orderid;

    private String orderno;

    private Integer userid;

    private Byte orderstatus;

    private BigDecimal goodsmoney;

    private Byte ispay;

    private Byte payfrom;

    private String username;

    private String gamename;

    private Date createtime;

    private String areaidpath;

    private String userphone;

    private String orderremarks;

    private BigDecimal realtotalmoney;

    private Integer orderscore;

    private Byte isappraise;

    private Byte isclosed;
}

主要看一下UserMapper.xml,因为是一对多的关系,所以下面这个查询语句是主要学习的,这个查询就是查询用户的信息和他名下的订单详情,包括结果类型,和参数类型,数据类型的设置都要注意。

<select id="getUserDetails" parameterType="Integer" resultMap="UserResultMap">
        select * from `user` u ,`order` o where u.id=o.userID and u.id=#{id}
   </select>
  <resultMap type="com.jerry.springbootdemo.entity.User" id="UserResultMap">
           <id column="id" property="id" jdbcType="INTEGER" />
           <result column="username" property="username" jdbcType="VARCHAR" />
           <result column="passsword" property="passsword" jdbcType="VARCHAR" />
           <result column="gender" property="gender" jdbcType="CHAR" />
           <result column="hobby" property="hobby" jdbcType="VARCHAR" />
             <!-- ofType指定order集合中的对象类型 -->
             <collection property="orderList" ofType="com.jerry.springbootdemo.entity.Order">
               <id column="orderID" property="orderid" jdbcType="INTEGER" />
               <result column="orderNo" property="orderno" jdbcType="VARCHAR" />
               <result column="userID" property="userid" jdbcType="INTEGER" />
               <result column="orderStatus" property="orderstatus" jdbcType="TINYINT" />
               <result column="goodsMoney" property="goodsmoney" jdbcType="DECIMAL" />
               <result column="isPay" property="ispay" jdbcType="TINYINT" />
               <result column="payFrom" property="payfrom" jdbcType="TINYINT" />
               <result column="userName" property="username" jdbcType="VARCHAR" />
               <result column="gameName" property="gamename" jdbcType="VARCHAR" />
               <result column="createTime" property="createtime" jdbcType="TIMESTAMP" />
               <result column="areaIdPath" property="areaidpath" jdbcType="VARCHAR" />
               <result column="UserPhone" property="userphone" jdbcType="CHAR" />
               <result column="orderRemarks" property="orderremarks" jdbcType="VARCHAR" />
               <result column="realTotalMoney" property="realtotalmoney" jdbcType="DECIMAL" />
               <result column="orderScore" property="orderscore" jdbcType="INTEGER" />
               <result column="isAppraise" property="isappraise" jdbcType="TINYINT" />
               <result column="isClosed" property="isclosed" jdbcType="TINYINT" />
             </collection>
       </resultMap>

UserController.java

一个是返回json,一个是返回view。

@GetMapping(value="/userdetails")
    public ModelAndView userDetalis(){
        ModelAndView mv=new ModelAndView();
        mv.addObject("details",userMapper.getUserDetails(1));
        mv.setViewName("UserDetails");
        return  mv;
    }
    @GetMapping(value = "/userjson/{id}")
    public @ResponseBody User userJson(@PathVariable() Integer id){
       User user1=userMapper.getUserDetails(id);
       return user1;
    }

swagger测试成功
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值