Springboot系列(九):mybatis-plus之自定义sql零基础教学
好了,我们开始这期的正文吧。
一、前言
mybatis-plus的基本使用,前两期基本讲的差不多,够日常使用,但是有的小伙伴可能就会抱怨了,若是遇到业务逻辑比较复杂的sql,都使用swagger 进行拆分组装?mybatis-plus动态拼接sql满足单表查询,若是遇到多表关联且条件复杂涉及分组就不是那么的灵活,那有办法满足该种特殊需求么?不好意思,还真有,mybatis-plus也早就预料到了会存在该种需求,便对该特殊有了特殊处理,继续沿用了他的兄弟mybatis自定义sql的功能,没想到吧!
二、如何自定义SQL
接下来我将为大家介绍两种解决方案。一是直接使用mybatis的注解@Select。二是创建.xml文件的形式。
1、使用注解 @Select()
还记得我们创建一整套控制器的时候,有一个文件夹命名为dao,它今天就是为了干这件事的。首先我们现在dao层先创建一个UserMapper,然后定义几个实例接口给大家看看,让大家熟悉怎么接口上加自定义SQL。
传参类型为String,Long,Integer等,传参直接使用。
使用@Param("xxx")设置参数 即可
参数就是使用@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等。
像这种集合形式,那得就通过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>复制代码
post测试,结果显而易见。单参数传递,参数名直接用 #{ 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 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
#{item}
如果传入的是单参数且参数类型是一个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>复制代码
接口分发层就自己琢磨啦。其实看bug菌postman调用url及请求方式,一看就都明白啦!有些还是得多靠小伙伴们自己从细节摸索,这样比我百分百教大家要理解的更为深刻。
伪原创工具 SEO网站优化 https://www.237it.com/
作者:bug菌
链接:https://juejin.cn/post/7035462492436299784