前言
我们前面只用SpringMVC完成了一个根据id模拟查询返回一个用户的例子,现在我们把之前的例子串联起来
这里呢我考虑了一下,我们暂时不用MyBatis-Plus
,还是只用MyBatis
,但是呢,我们之前不是看MyBatis-plus
官网说,对程序无侵入么,那我们就来试试,在MyBatis-Plus
中使用Mybatis
,哈哈,不要怕,就是要敢于尝试
项目结构
我们先来复习一下,跟MyBatis
相关的文件的位置配置主要有三个
Mybatis-config.xml
: 全局配置文件,在引入了MyBatis-Plus之后,这个可以放在了appplication.yml当中xxxMapper.java
接口:Mapper接口,我们在主配置类配置了@MapperScan(basePackages = "com.example.demo.mapper")
,指定了扫描的Mapper包,然后在类上加上@Repository
就可以了xxxMapper.xml
Mapper接口配置文件,这个文件我们查看application.yml
这一行配置了xxxMapper.xml
文件的地址,所以我们需要在resources
下面新建一个文件夹mapper
,并且新建mapper配置文件,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接口对应的相对路径-->
<mapper namespace="com.example.demo.mapper.UserMapper">
</mapper>
引入约束和名称空间,约束就是相当于一个写xml
的模板,会有提示还有lint功能,名称空间可以隔离和识别这里的实体类
MyBatis
的相关结构就完成了,哈哈,其实都是一回事儿
下面我们来引入Service
层
比较好的设计规范是,有一个接口类,和一个Service实现类
service
包下面放接口(UserService
),impl
子包下面放实现类(UserServiceImpl
)
package com.example.demo.service;
public interface UserService {
}
接口只用来定义行为,所有的实现(包括注入UserMapper
),都是在实现类里面完成的
package com.example.demo.service.impl;
import com.example.demo.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class UserServiceImpl {
@Autowired
UserMapper userMapper;
}
完成的项目结构如下
编写Mapper
这里就先想起来陆大佬之前在B站视频里写这个SpringBoot
的CRUD的时候很有意思的一个问题了,是从Controller写到Mapper还是反过来,哈哈,我们先把Mapper写好,复习一下之前的知识,然后使用测试类去测试,后面再去写Service把这两个连起来
package com.example.demo.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.demo.dataobject.UserDO;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;
@Repository
public interface UserMapper extends BaseMapper<UserDO> {
public UserDO selectById(@Param("id") Integer id);
}
<?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接口对应的相对路径-->
<mapper namespace="com.example.demo.mapper.UserMapper">
<select id="selectById" parameterType="Integer" resultType="UserDO">
select * from user where id=#{id}
</select>
</mapper>
可以发现一个很有意思的现象,这里爆红了,是为什么呢,哈哈,不是说好的无侵入么
我们翻一下之前在完成MyBatis-plus
的测试代码的时候,根据id查询用户是不是也是用的这个selectById
这个方法称,然后可以看到,我们的UserMapper.xml
继承了我们的BaseMapper<UserDO>
,很容易联想到,是不是我们的BaseMapper
里面已经自带了这个方法呢
我们很容易想到,两个方法只有在名称,返回类型,参数相同的情况下才会冲突,那么我们自己写的selectById
和BaseMapper<UserDO>
的selectById
,除了名称以外,返回类型和参数这两个是否也是相同的呢
实践才是检验真理的唯一标准,我们打开源码看看,按住ctrl
,就可以进入idea的进入源码的模式了,然后点击BaseMapper
,ctrl+f
打开搜索模式,输入方法名selectById
这里用了泛型T,我们在继承BaseMapper
的时候传入了UserDO
,这里的T就是相当于我们的UserDO
,所以方法的返回参数是一致的
然后参数类型 Serializable
,我们传入的是Integer
,我们同样的方法打开Integer
的源码
并没有看到直接继承Serializable
,只看到继承Number
和Comparable
,要是这样一层一层找下去也太麻烦了
这里idea有一个很强大的工具,可以轻松查看类之间的继承关系
我们在Interger界面右键,依次选择如图,点开
哈哈,果不其然,Integer是实现了这个接口的,根据向上转型,就真相大白了,源码其实也没有那么难对吧
所以咋办呢,咱们命名的时候就加个my
前缀标识一下吧,有更好的办法也可以评论区留言哈
public UserDO mySelectById(@Param("id") Integer id);
<select id="mySelectById" parameterType="Integer" resultType="UserDO">
select * from user where id=#{id}
</select>
写个测试类测试一下
/**
* 测试根据id查询用户 mybatis
*/
@Test
public void testMySelectById() {
UserDO userDO = userMapper.mySelectById(6);
System.out.println(userDO.getUsername());
}
这样,我们就在Mybatis-Plus
里面使用了MyBatis
了,哈哈,是不是有种5g
回到了2g
时代的感觉
但小周同学还是秉持着一个观点的:只要能解决问题的技术,就是好技术
这节太长了,就暂时到这里吧
下次我们把Service接进来