MybatisPlus通过Mapper、IService接口为我们提供了大量的默认方法来实现CRUD(增删改查)的需求,但若是要实现多表关联查询,或者根据不同的查询条件传参,就需要自定义Sql了!
目录
源码地址:尹煜 / mybatis_plus_study · GitCode
1 XML文件配置
在 xml 文件配置环节可谓是十分重要了,为此我捣鼓了一晚上,若是按照本文配置流程,亲测有效,完成效果👇,因为我安装了MyBatisX插件,所以会出现小鸟icon,为生产力助力~
1.1 新建xml软件包和UserMapper.xml
首先创建存放 xml 文件的位置,我选择将它放在了和 UserMapper 的同一目录下,方便对照查看(另一种是选择放在 resources 资源目录下,看个人喜好~)
xml 文件里边放着连个方法,一个是异表查询,一个是两表查询,关键的是:
namespace:对应mapper的包.类名
id:对应mapper接口下的方法名
resultType:返回数据的类型
路径:src/main/java/com/yinyu/mapper/xml/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.yinyu.mapper.UserMapper">
<select id="selectUser" resultType="com.yinyu.pojo.User">
select * from user
${ew.customSqlSegment}
</select>
<select id="multiTableQuery" resultType="java.util.Map">
select
*
from user u
left join student s on u.id=s.id
where u.name=#{name}
</select>
</mapper>
1.2 xml文件路径配置
我选择的是将该路径配置在 properties 里边,也可以将其配置在application.yaml里边,二选一,并且我将文件路径具体化化了,com/yinyu/mapper/xml/*.xml 就是 xml 文件的相对路径。
并且因为我引用的是mybatis-plus-boot-starter 依赖,所以配置 mybatis-plus.mapper-locations;若是mybatis-plus 依赖,则配置 mybatis.mapper-locations。
路径:src/main/resources/application.properties
#xml文件路径配置
mybatis-plus.mapper-locations= classpath:com/yinyu/mapper/xml/*.xml
application.yaml(择其一):
mybatis-plus:
mapper-locations: classpath*:/mapper/*Mapper.xml
1.3 解决maven无法编译XML文件
其实,按照上述流程就可以实现 xml 配置了,但是我调用自定义SQL的方法后会报错找不到对应的接口,花了蛮久时间终于找到了解决办法,在 pom 文件中加入以下代码👇,碰到相同问题的同学可以试试:
<!-- MAVEN项目部署时无法将mapper.xml文件部署,需要通过以下配置解决 -->
<build>
<!--资源往往不是代码,无需编译,而是一些properties或XML配置文件,构建过程中会往往会将资源文件从源路径复制到指定的目标路径。-->
<resources>
<resource>
<!--directory,资源文件的路径,默认位于${basedir}/src/main/resources/目录下-->
<directory>src/main/java</directory>
<!--includes,一组文件名的匹配模式,被匹配的资源文件将被构建过程处理-->
<includes>
<include>**/*.xml</include>
</includes>
<!--excludes:指定哪些文件被忽略,如果一个文件同时符合includes和excludes,则excludes生效;-->
<excludes>
<exclude>**/*.properties</exclude>
</excludes>
<!--filtering,构建过程中是否对资源进行过滤,默认false-->
<filtering>false</filtering>
</resource>
</resources>
</build>
2 XML实现CRUD
前期准备工作完成之后就可以写方法代码了~SQL语句也可放在这时候写,我是为了方便,所以直接贴在了前边~
2.1 xml 实现单表查询
①@Param(Constants.WRAPPER) Wrapper wrapper 作为入参,但需要在 xml 里边加${ew.customSqlSegment}
路径:src/main/java/com/yinyu/mapper/UserMapper.java
//xml查询user
List<User> selectUser(@Param(Constants.WRAPPER) Wrapper wrapper);
②对应的SQL,写在 src/main/java/com/yinyu/mapper/xml/UserMapper.xml:
③对应的 test 方法,写在 src/test/java/com/yinyu/CustomizeSqlTest.java
需要注意的是因为设置了 Wrapper 作为入参,所以需要 new 一个,入参若是 null 就会报错。
@Test
public void sqlTest3(){
QueryWrapper<User> wrapper = new QueryWrapper<>();
List<User> result = userMapper.selectUser(wrapper);
System.out.println(result);
}
④查询成功:
2.2 xml 实现多表查询
①首先需要在数据库中拥有第二张数据表,student表如下:
②@MapKey("id") 的作用是告诉mybatis封装这个map的时候,使用哪个属性作为map的key,不然会报错~
路径:src/main/java/com/yinyu/mapper/UserMapper.java
//xml实现多表查询 name作为入参
@MapKey("id")
List<Map<String,Object>> multiTableQuery(@Param("name") String name);
③对应的SQL,写在 src/main/java/com/yinyu/mapper/xml/UserMapper.xml:
④对应的 test 方法,写在 src/test/java/com/yinyu/CustomizeSqlTest.java:
#{name}也就是入参"尹煜"~
@Test
public void sqlTest4(){
List<Map<String, Object>> result = userMapper.multiTableQuery("尹煜");
System.out.println(result);
}
⑤查询成功:
3 注释@Select 方式实现CRUD
注解方式相比 xml 要简单一些,不用复杂的配置,只需要在对应抽象方法上添加注释及语句即可👇,不过实现不如 xml 强大 。
3.1 注释 + wrapper 查询
①抽象方法编写
路径:src/main/java/com/yinyu/mapper/UserMapper.java
查询是用 @Select 注释,后边加SQL语句,若入参设置 Wrapper 需要如下编写👇
//查询user
@Select("select * from user ${ew.customSqlSegment}")
List<User> selectUserTable(@Param(Constants.WRAPPER) Wrapper wrapper);
②对应的 test 方法,写在 src/test/java/com/yinyu/CustomizeSqlTest.java:
@Test
public void sqlTest1(){
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper
.isNotNull("name");
List<User> result = userMapper.selectUserTable(wrapper);
System.out.println(result);
}
③查询成功:
3.2 注解实现异表查询
很多情况下我们需要对另一张表进行查询,不只是 xml ,其实注释也可实现
①数据库的另一张 student 表:
②抽象方法编写
因为返回数据不是 user 实体类,所以用 map 替代,实际业务的话会用 dto(dto 用于合并两个实体类的字段)
路径:src/main/java/com/yinyu/mapper/UserMapper.java
//查询student,也可创建student实体类替代Map
@Select("select * from student")
List<Map<String,Object>> selectStudentTable();
③对应的 test 方法,写在 src/test/java/com/yinyu/CustomizeSqlTest.java:
@Test
public void sqlTest2(){
//因为没有创建Student实体类,所有用Map装数据
List<Map<String, Object>> result = userMapper.selectStudentTable();
System.out.println(result);
}
④查询成功:
总结
大家如果有疑问都可以评论提出,有不足之处请大家批评指正,之后可能会推出代码生成器~