首页 > 数据库 >MyBatis 多条件查询、动态SQL、多表操作、注解开发,应有尽有,一网打尽!

MyBatis 多条件查询、动态SQL、多表操作、注解开发,应有尽有,一网打尽!

时间:2022-09-20 08:22:32浏览次数:110  
标签:多表 ur SQL MyBatis id 属性

点击关注 程序员闪充宝 2022-09-19 17:42 发表于山西




MyBatis封装了JDBC通过Mapper代理的方式,以前繁琐的操作通过“属性与字段映射”就简单化解,MyBatis的动态SQL完美展现了DBMS的独特魅力。

一、多条件查询

基于Mybatis的多条件查询,是在Mapper代理的映射文件中写上原有的SQL,然后接口中写一个带参的方法即可,就像这样:

image

相比于原生的JDBC那一套,通过MyBatis确实解决了不少硬编码的问题

但是用户的查询永远是动态的操作,他可能在多个条件中选择其中少量条件进行查询,我们的SQL是死的,而用户需求对应的SQL却是活的,这样就会造成不匹配而形成语法错误

比如,根据这张表,若是要根据部分字段查出整体,我们可以写对应需求的SQL,但是我要是查询的条件变少了或者变多了呢?若用户只想通过一个条件来查询,那么在其他占位符的位置不输入于是成了null,过不了语法自然查不了,还得重新写SQL,多麻烦

image

这个时候MyBatis的特色就体现出来了——动态SQL。

二、动态SQL

SQL语句会随着用户的输入或者外部条件的变化而变化,则称之为动态SQL。另外,最新 MyBatis 系列面试题整理好了,大家可以在Java面试库小程序在线刷题。

1. if-where

因为采用了Mapper代理开发,我们可以通过写xml的形式来编写我们的SQL,动态SQL的特性也就在这一举动中所蕴育,在原有的Mapper文件里我们进行如下改造,让平平无奇的SQL焕然一新:

<select id="selByCondition" resultMap="rm">
    select *
    from mybatis
    <where>
    <if test="status !=null">
       and STATUS=#{STATUS}
    </if>
    <if test="companyName !=null and companyName !=''">
    and company_name like #{companyName}
    </if>
    <if test="bracdName !=null and bracdName !=''">
    and bracd_name like #{bracdName}
    </if>
    </where>
</select>

<where>标签可以自动帮我们去掉and”,这样,不管查询的条件怎么变,我跟着这个逻辑流程走就不会出现SQL语法毛病而导致查询不出来的毛病啦,因为null的情况已经被if所过滤掉了,真是太哇塞了!

2. choose-when-ortherwise

对于从多个条件中选择一个的单条件查询的场景,利用分支嵌套就可以实现动态选择单条件:

在MyBatis的Mapper代理中,<choose>相当于switch,<when>相当于case

<select id="selByCondition2" resultMap="rm">
    select *
    from mybatis where
    <choose>
        <when test="status !=null">
            STATUS=#{STATUS}
        </when>
        <when test="companyName !=null and companyName !=''">
            company_name like #{companyName}
        </when>
        <when test="bracdName !=null and bracdName !=''">
            bracd_name like #{bracdName}
        </when>
        <otherwise>1=1</otherwise>
    </choose>
</select>

与多条件查询不同的是,SQL语句中只会有一个分支生效

当用户一个条件都不选时,可以在<otherwise>中写上1=1让语法成立,反之,若选择了条件则会返回正常结果。

推荐一个开源免费的 Spring Boot 最全教程:https://github.com/javastacks/spring-boot-best-practice

3. foreach

对于批量删除的场景,传统的方法是通过in关键字结合占位符来确定,就像这样

where id in (?,?,?)

但对于动态的场景,批量的数量永远是不确定的,这就导致还需要去改SQL里的占位符数量啊,又是一件麻烦事

PS:MyBatis会将数组参数封装成一个Map集合,默认情况(K-V)array=数组。

下面使用了@Param注解改变了map集合中默认的key

image

于是MyBatis中的<foreach>解决了这一麻烦。

本质是通过遍历的形式,批量删除的数据是由id数组或者集合来决定,collection属性决定了要遍历哪个数组/集合,item属性则来存放选出的元素,并把它放在占位符里,separator属性表示分隔符

<delete id="deleteById">
    delete frpm mybatis where id in
    <foreach collection="ids" item="id" separator="," open="(" close=")">
        #{id}
    </foreach>;
</delete>

有人会问为啥这里只有一个#{id},我的属性字段不止这一个呀?此id非彼id他是一个数组/集合。

三、多表操作

多表之间的关系有一对一,一对多,多对一,多对多,每一种都有建表的原则,以用户-订单模型为例

利用传统的方法进行多表查询无非是通过id来连接表然后封装返回结果,MyBatis中也是如此,我们在Mapper文件中写好表字段之间的映射关系,定义好类型即可,只不过这一过程有点复杂,但一次配好之后即可极大减少硬编码问题,提高效率。

1. 一对一

一个用户有一张订单

image

首先还是那套路,建好实体类,写好接口方法,配置Mapper文件,而多表操作的麻烦点就在于配置文件,这里通过例子细说一下

1.先把表写好
CREATE TABLE orders (
id INT PRIMARY KEY ,
ordertime VARCHAR(20) NOT NULL DEFAULT '',
total DOUBLE,
uid INT);
INSERT INTO orders VALUES(1,2020,2000,1);
INSERT INTO orders VALUES(2,2021,3000,2);
INSERT INTO orders VALUES(3,2022,4000,3);
CREATE TABLE USER (
id INT PRIMARY KEY ,
username VARCHAR(50) NOT NULL DEFAULT '',
passwords VARCHAR(50) NOT NULL DEFAULT '');
INSERT INTO USER VALUES(1,'lyy',333);
INSERT INTO USER VALUES(2,'myy',444);
INSERT INTO USER VALUES(3,'xyy',555);

2.写Mapper配置文件

在写实体类时,要把一个实体写到另一个实体的属性里面,这样才体现关联性,就比如“订单是所用户拥有的”,正因为这种关系我们才会在订单实体类里面写上private User user;这一属性,这样根据id连接的两个实体才能完美对接!

就像这样:

image

通过<association>把两张表对应的实体类连接起来,只不过是主键ID要用单独的标签

  • property: 当前实体(order)中的属性名称(private User user)
  • javaType: 当前实体(order)中的属性的类型(User)

这两个user有着本质上的却别,就好像前者是在一个人的名字,后者正是被叫的那个人,MyBatis好像就利用了这一特性,通过标签的形式连接了两个实体

<select id="findAll" resultMap="orderMap">
   SELECT *,o.id oid FROM orders o,USER u WHERE o.uid=u.id
</select>

2.一对多

一个用户有多张订单

image

首先,在原有的User实体中得加上一个表示“用户有哪些订单的属性”private List<Order> orderList;,目的是为了把订单的信息封装到用户的这个属性里,在Mapper文件中体现:

<collection property="orderList" ofType="order">
    <!--封装order的数据-->
    <id column="oid" property="id"></id>
    <result column="ordertime" property="ordertime"></result>
    <result column="total" property="total"></result>
</collection>

  • property:集合名称,User实体中的orderlist属性
  • ofType:当前集合中的数据类型,就是order实体

然后就是写一对多的SQL:

<select id="findAll" resultMap="userMap">
   SELECT *,o.id oid FROM USER u,orders o WHERE u.id=o.uid
</select>

总结来看,一对多相比于一对一就是在那个“一”中增添了封装“多”的属性而已,然后稍微调整一下SQL。另外,最新 MyBatis 系列面试题整理好了,大家可以在Java面试库小程序在线刷题。

3.多对多

多用户多角色

image

         多表的连接是靠中间表,这点在Mapper文件中通过映射实现,具体是把两张外表的id(userId和roleId)在id标签中配置成同一个属性,就像这样:SQL环节就得用多对多的套路了

         多表的连接是靠中间表,这点在Mapper文件中通过映射实现,具体是把两张外表的id(userId和roleId)在id标签中配置成同一个属性,就像这样:SQL环节就得用多对多的套路了         多表的连接是靠中间表,这点在Mapper文件中通过映射实现,具体是把两张外表的id(userId和roleId)在id标签中配置成同一个属性,就像这样:SQL环节就得用多对多的套路了

         多表的连接是靠中间表,这点在Mapper文件中通过映射实现,具体是把两张外表的id(userId和roleId)在id标签中配置成同一个属性,就像这样:SQL环节就得用多对多的套路了

         多表的连接是靠中间表,这点在Mapper文件中通过映射实现,具体是把两张外表的id(userId和roleId)在id标签中配置成同一个属性,就像这样:SQL环节就得用多对多的套路了

         多表的连接是靠中间表,这点在Mapper文件中通过映射实现,具体是把两张外表的id(userId和roleId)在id标签中配置成同一个属性,就像这样:SQL环节就得用多对多的套路了

         多表的连接是靠中间表,这点在Mapper文件中通过映射实现,具体是把两张外表的id(userId和roleId)在id标签中配置成同一个属性,就像这样:SQL环节就得用多对多的套路了

         多表的连接是靠中间表,这点在Mapper文件中通过映射实现,具体是把两张外表的id(userId和roleId)在id标签中配置成同一个属性,就像这样:SQL环节就得用多对多的套路了

         多表的连接是靠中间表,这点在Mapper文件中通过映射实现,具体是把两张外表的id(userId和roleId)在id标签中配置成同一个属性,就像这样:SQL环节就得用多对多的套路了

四、注解开发

针对于简单的CRUD注解开发可以极大地提升效率,顾名思义就是把SQL写在注解里

查询(@Select):image

添加(@Insert):

image

修改(@Update):

image

删除(@Delete) :

image

精彩推荐:

SpringBoot+ShardingSphereJDBC实现读写分离!

标签:多表,ur,SQL,MyBatis,id,属性
From: https://www.cnblogs.com/ios9/p/16709787.html

相关文章

  • Java学习-第一部分-第三阶段-第三节:MySQL基础
    零基础学MySQL笔记目录:(https://www.cnblogs.com/wenjie2000/p/16378441.html)一个问题淘宝网,京东、微信,抖音都有各自的功能,那么当我们退出系统的时候,下次再访问时,为什......
  • 【数据库】C#使用ADO.NET操作sqlite数据库 --Microsoft.Data.Sqlite
    概述操作sqlite数据库之前你必须了解:ADO.NET、数据提供程序等知识点,以下简单介绍。ADO.NET是微软公司提供的一款全新的数据库访问技术,是在.NETFramework中负责数据访问......
  • 【数据库】OLE-DB、ODBC、ADO.NET、ADO、sql sever .net、 sqlite .net是什么
    概览OLE-DB、ODBC、ADO.NET、ADO、sqlsever.net、sqlite .net面像对象的数据库访问技术,可以将他们比喻为数据库应用程序和数据源之间的桥梁ODBC:访问关系型数据库OL......
  • MySQL实现备份案例(2)
    案例1:MySQL8.0实现数据库冷备份和还原10.0.0.10--MySQL8.0#停止数据库[[email protected]]#systemctlstopmysqld.service#备份数据[root@CentOS8~]#scp-......
  • mysql忘记密码找回
     Windows下如果MySQL密码忘记了root密码导致无法登录,如下图所示,   这个时候怎么办,只能重置root密码了。1.打开任务管理器查看MySql服务是否启动,如果已启动则先......
  • MySQL实现备份(1)
    基础知识:备份类型:完全备份和部分备份冷备份、热备份、温备份温备份适用于:myisam热备份适用于:innodb物理备份和逻辑备份完全备份和部分备份完全备份:备份所......
  • 大家都在用MySQL count(*)统计总数,到底有什么问题?
    在日常开发工作中,我经常会遇到需要统计总数的场景,比如:统计订单总数、统计用户总数等。一般我们会使用MySQL的count函数进行统计,但是随着数据量逐渐增大,统计耗时也越来越长......
  • mybatis中的#和$的区别
    ​/**作者:呆萌老师*☑csdn认证讲师*☑51cto高级讲师*☑腾讯课堂认证讲师*☑网易云课堂认证讲师*☑华为开发者学堂认证讲师*☑爱奇艺千人名师计划成员*在这里给大......
  • mysql 在insert时防止出现主键冲突错误的方法
    在mysql中插入数据的时候常常因为主键存在而冲突报错,下面有两个解决方法:1、在insert语句中添加ignore关键字,如:insertignoreintotable(id,name)values('1','usern......
  • MySQL-索引
    MYSQL之索引本章包含索引概述,索引结构,索引语法,索引分类,SQL性能分析,索引使用,索引设计原则!索引概述介绍(1)索引(index)是帮助MySQL高效获取数据的数据结构(有序)。......