springboot系列:mybatis-plus之如何自定义sql|超级详细,建议收藏

Posted bug菌¹

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了springboot系列:mybatis-plus之如何自定义sql|超级详细,建议收藏相关的知识,希望对你有一定的参考价值。

👨‍🎓作者:bug菌

🎉简介:在CSDN、掘金等社区优质创作者,全网合计6w粉+,对一切技术都感兴趣,重心偏java方向。

🚫特别声明:原创不易,转载请附上原文出处链接和本文声明,谢谢配合。

🙏版权声明:文章里可能部分文字或者图片来源于互联网或者百度百科,如有侵权请联系bug菌处理。

【开发云】年年都是折扣价,不用四处薅羊毛

         嗨,家人们,我是bug菌呀,我又来啦。今天我们来聊点什么咧,OK,接着为大家更《springboot零基础入门教学》系列文章吧。希望能帮助更多的初学者们快速入门!

       小伙伴们在批阅文章的过程中如果觉得文章对您有一丝丝帮助,还请别吝啬您手里的赞呀,大胆的把文章 点亮👍吧,您的点赞三连( 收藏⭐️+关注👨‍🎓+留言📃)就是对bug菌我创作道路上最好的鼓励与支持😘。时光不弃🏃🏻‍♀️,创作不停💕,加油☘️

一、前言🔥

        mybatis-plus的基本使用,前两期基本讲的差不多,够日常使用,但是有的小伙伴可能就会抱怨了,若是遇到业务逻辑比较复杂的sql,都使用swagger 进行拆分组装?mybatis-plus动态拼接sql满足单表查询,若是遇到多表关联且条件复杂涉及分组就不是那么的灵活,那有办法满足该种特殊需求么?不好意思,还真有,mybatis-plus也早就预料到了会存在该种需求,便对该特殊有了特殊处理,继续沿用了他的兄弟mybatis自定义sql的功能,没想到吧!

二、如何自定义SQL🔥

        接下来我将为大家介绍两种解决方案。一是直接使用mybatis的注解@Select。二是创建.xml文件的形式。

1️⃣使用注解 @Select()

       还记得我们创建一整套控制器的时候,有一个文件夹命名为dao,它今天就是为了干这件事的。首先我们现在dao层先创建一个UserMapper,然后定义几个实例接口给大家看看,让大家熟悉怎么接口上加自定义SQL。
  • 传参类型为String,Long,Integer等,传参直接使用。
  1. 使用@Param("xxx")设置参数 即可
  2. 参数就是使用@Param设置的value值 即可。

代码演示:

@Select("select * from user where id = #userId")
UserEntity getUserById(@Param("userId") String userId);

使用postman请求一下:localhost:8080/user/getUser-by-id?userId=1;查看控制台打印SQL:

 ok!参数设置成功,查询结果一条。

  • 传参类型为.class类,比如XxxModel,XxxEntity等。
        获取参数就是直接通过你指定的Param的value对象,对象点属性,这样,比如如下指定的是model那要获取model的sex值,那就是model.sex 即可。

代码演示:

@Select("select * from user u left join grade g on u.id = g.student_id  where u.sex = #model.sex and g.name = #model.className")
List<UserEntity> getUsers(@Param("model")QueryUserInfoModel model);

使用postman请求一下,设置好参数。请看返回结果:

  • 传参类型为集合类,比如List<Integer>等。

像这种集合形式,那得就通过xml文件的形式配置啦。

2️⃣使用xxx.xml文件

        先新建一个UserMapper.xml 然后指定 mapper namespace 即可。
  • 传参类型为String,Long,Integer等,传参直接使用。

持久层UserMapper.java

UserEntity getUserById(@Param("userId") String userId);

UserMapper.xml

    <!--根据userId查询-->
    <select id="getUserById" resultType="com.example.demo.Entity.UserEntity">
        select * from user where id = #userId
    </select>

        postman测试,结果显而易见。单参数传递,参数名直接用 # param  就可以获取到。

  • 若传参类型为class类等,比如QueryUsersModel、UserEntity等。

UserMapper.java 配置如下:

List<UserInfoVo> getUsers(@Param("model")QueryUserInfoModel model);

        UserMapper.xml  配置如下:跟你sql语句没多大区别,唯独就是参数获取方式,这个大家得注意一下。

<!--根据性别和班级名称查询-->
<select id="getUsers"  resultMap="BaseResultMap">
    select u.name as name,g.name as className from user u left join grade g on u.id = g.student_id  where u.sex = #model.sex and g.name = #model.className
</select>

        postman接口测试一下,给定参数。然后点击Send发出请求,返回结果如下。

  • 传参类型为集合,比如ArrayLis<Integer> userIds,String [] ids等。

UserMapper.java

//userIds 用户id集合List<UserInfoVo>
 getUsersByIds(@Param("userIds")List<Integer> userIds) ;

UserMapper.xml 

<!--根据用户ids遍历查询-->
<select id="getUsersByIds"  resultMap="BaseResultMap">
     select u.name as name , g.name as className from user u left join grade g on u.id = g.student_id
     where 1=1
    <if test="userIds.size() !=0">
        and u.id in
        <foreach collection="userIds" item="userId" open="(" separator="," close=")" >
            #userId
        </foreach>
    </if>
</select>

postman测试一下,看看是否查询出指定id("userIds":[1,2,3])所对应的用户信息;

        结果也是直接返回。证明接收数组也是没有任何问题。

        接着不知道你们有没有 注意到,我在sql上多拼接了这一句:" where 1=1 ",有哪位小伙伴知道这是为何多此一举么?欢迎评论区告诉bug菌。

        提示大家一部分,我userIds传了个空进来,查询出了所有数据结果,结果是正常的。

三、拓展🔥

1️⃣.xml 常用参数说明

一句话总结来说就是:

        resultType用于返回已经定义好的domain,pojo或者jdk定义的基本数据类型,返回的属性需要和domain的属性是一样的,否则是绑定不上的; 

        而 resultMap是指向一个外部的引用resultMap,当表名和列表不一致时使用resultMap做个映射,但在处理返回结果是基本类型的时候是无能为力的;比如我代码里用到的BaseResultMap,其实就是表字段名与对象中属性名做的映射,column属性指定的是sql返回集对于的字段名,而property指定的是你pojo中的属性字段名称。

2️⃣.xml foreach语法解读

如下边这段

<foreach collection="userIds" item="userId" open="(" separator="," close=")" >
    #userId
</foreach>
解读:其实很好理解。foreach的主要用在构建 in条件中,它可以在SQL语句中进行迭代一个集合。

foreach元素的属性主要有 item,index,collection,open,separator,close。

其中item表示集合中每一个元素进行迭代时的别名, index指 定一个名字,用于表示在迭代过程中,每次迭代到的位置, open表示该语句以什么开始, separator表示在每次进行迭代之间以什么符号作为分隔符, close表示以什么结束。 collection属性,是必须指定的。可以是list,array数组、map等。

 注意:

  • 如果传入的是单参数且参数类型是一个List的时候,collection属性值为list
<foreach collection="list" index="index" item="item" open="(" separator="," close=")">
    #item
</foreach>
  • 如果传入的是单参数且参数类型是一个array数组的时候,collection的属性值为array。
<foreach collection="array" index="index" item="item" open="(" separator="," close=")">
    #item
</foreach>
  • 如果传入的参数是多个的时候,我们就需要把它们封装成一个Map了,当然单参数也可。
 <select id="selectFor" parameterType="java.util.HashMap" resultType="Blog">
        select * from tb_log where title like "%"#title"%" and id in
          <foreach collection="ids" index="index" item="item" open="(" separator="," close=")">
               #item
          </foreach>
 </select>

四、附上部分完整源码🔥

        如下我就把持久层跟xml配置给小伙伴完成展示一下,其余用到的model 、vo等就按照自己的习惯啦,真正需要的也可以评论区告诉我,我会为大家一一解答的。

UserMapper.java

@Component
public interface UserMapper extends BaseMapper<UserEntity> 

    UserEntity getUserById(@Param("userId") String userId);

    List<UserInfoVo> getUsers(@Param("model")QueryUserInfoModel model); 

    List<UserInfoVo> getUsersByIds(@Param("userIds")List<Integer> userIds) ;

UserMapper.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.example.demo.dao.UserMapper">
   
 <!-- 通用查询映射结果 -->
    <resultMap id="BaseResultMap" type="com.example.demo.Vo.UserInfoVo">
        <result column="name" property="name" />
        <result column="className" property="className" />
    </resultMap>

    <!--根据userId查询-->
    <select id="getUserById" resultType="com.example.demo.Entity.UserEntity">
        select * from user where id = #userId
    </select>

    <!--根据性别和班级名称查询-->
    <select id="getUsers"  resultMap="BaseResultMap">
        select u.name as name,g.name as className from user u left join grade g on u.id = g.student_id  where u.sex = #model.sex and g.name = #model.className
    </select>

    <!--根据用户ids遍历查询-->
    <select id="getUsersByIds"  resultMap="BaseResultMap">
         select u.name as name , g.name as className from user u left join grade g on u.id = g.student_id
         where 1=1
        <if test="userIds.size() !=0">
            and u.id in
            <foreach collection="userIds" item="userId" open="(" separator="," close=")" >
                #userId
            </foreach>
        </if>
    </select>

</mapper>
/**
 * 用户基本信息实体
 */
@TableName("user")
@Data
public class UserEntity implements Serializable 

    private static final long serialVersionUID = 1L;

    @TableId(value = "id", type = IdType.AUTO) //表示该id为自增,新增时候不需要手动设置id。
    private Integer id;

    @TableField(value = "name")
    private String name;

    @TableField(value = "age")
    private Integer age;

    @TableField(value = "sex")
    private String sex;

    @TableField(value = "address")
    private String address;

    @TableField(value = "describes")
    private String describes;

    @Override
    public String toString() 
        return this.id + " - " + this.name+ " - " +this.getSex();
        
    
/**
 * 班级信息实体
 */
@TableName("grade")
@Datapublic class GradeEntity 
    
    @TableId(value = "id", type = IdType.AUTO) //表示该id为自增,新增时候不需要手动设置id。
    private Integer id;

    @TableField(value = "name")
    private String name;

    @TableField(value = "student_id")
    private Integer studentId;

    @TableField(value = "create_time")
    private Date createTime;

    @TableField(value = "update_time")
    private Date updateTime;
/**
 * 返回用户班级信息
 */
public class UserInfoVo 

    private String  name;
    private String className;

    public String getName() 
        return name;
    
    public void setName(String name) 
        this.name = name;
    
    public String getClassName() 
        return className;
    
    public void setClassName(String className) 
        this.className = className;
    

        接口分发层就自己琢磨啦。其实看bug菌postman调用url及请求方式,一看就都明白啦!有些还是得多靠小伙伴们自己从细节摸索,这样比我百分百教大家要理解的更为深刻。

五、往期推荐🔥

六、文末🔥

        如果还想要学习更多,小伙伴们可关注bug菌专门为大家创建的专栏《springboot零基础入门教学》,从无到有,从零到一!希望能帮助到更多小伙伴们。

【开发云】年年都是折扣价,不用四处薅羊毛

       我是bug菌,一名想走👣出大山改变命运的程序猿。接下来的路还很长,都等待着我们去突破、去挑战。来吧,小伙伴们,我们一起加油!未来皆可期,fighting!

        最后送大家两句我很喜欢的话,与诸君共勉!


☘️做你想做的人,没有时间限制,只要愿意,什么时候都可以start。

🍀你能从现在开始改变,也可以一成不变,这件事,没有规矩可言,你可以活出最精彩的自己。


​​​

💌如果文章对您有所帮助,就请留下您的吧!(#^.^#);

💝如果喜欢bug菌分享的文章,就请给bug菌点个关注吧!(๑′ᴗ‵๑)づ╭❤~;

💗如果对文章有任何疑问,还请文末留言或者加群吧;

💞鉴于个人经验有限,所有观点及技术研点,如有异议,请直接回复参与讨论(请勿发表攻击言论,谢谢);

💕版权声明:原创不易,转载请附上原文出处链接和本文声明,版权所有,盗版必究!!!谢谢。

以上是关于springboot系列:mybatis-plus之如何自定义sql|超级详细,建议收藏的主要内容,如果未能解决你的问题,请参考以下文章

springboot系列:mybatis-plus之如何自定义sql|超级详细,建议收藏

springboot系列:mybatis-plus之条件构造器使用手册|超级详细,建议收藏

springboot系列:mybatis-plus之条件构造器使用手册|超级详细,建议收藏

springboot系列:如何通过mybatis-plus实现接口增删改查|超级详细,建议收藏

springboot系列:如何通过mybatis-plus实现接口增删改查|超级详细,建议收藏

SpringBoot整合MyBatis-Plus3.1详细教程