目录
[🌵MyBatis XML配置文件](#🌵MyBatis XML配置文件)
🌵本节目标
1.使用MyBatis完成简单的增删改查操作,参数传递。
2.掌握MyBatis的两种写法:注解和XML方式。
3.掌握MyBatis相关的日志配置。
这节开始,我们就开始分享一下我对mybatis的上手和理解吧,话说JDBC也能操作数据库,但是吧,我感觉啊,我当初学的时候,也很蒙,现在我应该是不记得一点了吧,我们的spring也知道传统的JDBC写起来成本很高,很麻烦,所以spring引入了mybatis。
🌵创建工程
创建springboot工程,并导入mybatis的起步依赖,mysql的驱动包。

发现

自动导入了mysql驱动包,和下面的mybatis依赖包。
🌵数据准备
准备user_info表

准备UserInfo对象

这个包名为啥叫model呢,这其实一种"名字约定",表示这个包底下的类都是实体类,当然你不想这么写,也可以写成其他的,都是ok。
🌵写一个最简单的访问数据库的代码

@Select,写sql查询语句的注解,此注解写在抽象方法上,表示此抽象方法如果被调用,将执行注解表示的sql语句。
@Mapper,加在接口类上,表示我们让spring帮我们自动创建一个实现了UserInfoMapper的对象,并重写了里面的所有方法,此时getList()方法就被重写了。
当然可能有些人想不通,会说为啥要搞一个接口,在这个接口里写sql语句?这是一种mybatis语法嘛?
我的回答:是的,这是MyBatis的语法,它选择用"接口"来组织SQL,而不是用"类"或"字符串常量",是为了让代码更优雅,更安全,更好维护。
🌵3层架构的落实

这是我们项目的结构,3层架构体现为,controller控制层,

然后是service业务逻辑层,

虽然只是调用一下Dao层,但必须写,这是规范。
最后是mapper数据访问层,写对应的sql语句。

🌵启动项目
好吧,我们逻辑都写完了,代码也写完了,启动一下项目吧

启动完之后,发现启动失败了,原因不在于我们的sql语句的问题,也不在我们写的代码的问题,原因就在于我们没告诉spring,要连接哪个数据库,而不是sql语句里一句简单的我要查询这张表,所以我们前面创建springboot工程,并导入mybatis的起步依赖,mysql的驱动包,但还不够,还要告诉spring我们这个sql语句连接的是mysql里的哪个数据库!
在yml文件里添加mybatis连接mybatis_test数据库的相关操作

url:你要告诉mybatis你将要连接mysql里的哪个数据库。
password:告诉mysql数据库的密码
driver-class-name:导入jdbc驱动,虽然我们前面最开始创建项目的时候,导入mybatis的起步依赖,mysql的驱动包,但我们还是要再次跟mybatis明确一下,底层用的是JDBC!
启动成功

我们访问一下,

访问返回成功!
但是从返回的结果来看,我们还是发现有问题的,

我们可以看到这3个属性对应都为null,可我们user_info表里存的是

这显然我们的java对象没有拿到,我们回看我们定义的UserInfo对象

发现没,就拿user_info表的delete_flag字段和UserInfo对象的deleteFlag属性来讲吧,它们名字都不一样,你还指望我们mybatis啥也给你弄好,那它是不是太牛马了,你想是吧,这背后是不是存在一种映射关系呢?我想是有的,所以这就是返回结果有点问题的原因!
🌵接口测试
就是像上面的通过URL访问,我们感觉太麻烦了,我们希望通过spring自己来测试,所以这就引出来了,我们spring的接口测试。
在我们需要测试的接口类里,右击鼠标,

选这个,然后会出现,

再选Test,
最后出现,

选中我们需要测试的方法,生成的测试名字,就是测试的那个接口名后加Tests,然后我们spring项目都有个test测试包

它就是放在我们项目名的下一级里。
生成这样子,是一个java类。

写测试的具体逻辑,

运行,

和我们上面的通过URL访问返回的结果一样。但是我觉得,这个返回结果和我们的spring测试用例启动的打印信息黏在了一起,看起来不够清晰。
配置yml格式的mybatis打印日志,

启动测试,打印结果,

🌵注解-增删改查
首先给大家科普一下mysql对于单引号和反引号的应用吧

字段加的是反引号,也可加可不加。
字段对应的值加的是单引号,也可加可不加。
🌵查
🍀单个参数传递
接口写法

测试


正常,我们通过#{id} 来给要传入的变量id进行占位,虽然占位多少有些勉强,甚至不能这么讲,但等到下面合适的时候,我再跟大家聊聊它背后是咋做的吧,先这样理解。
可是我想啊,假如占位的那个#{id}我改成#{id1}呢,反正只有一个参数,就算id1和id匹配不上,我们的mybatis和spring难道不会给我们进行优化嘛,验证一下,


结果,

说明传递一个参数时,确实名字可以不一样,也能正确执行!
🍀多个参数传递
接口写法

测试


这样也是可以拿到两个值的。
🍀参数重命名
接口写法

测试


测试成功!但是这种写法我们基本不用,看个人喜好吧。因为我们前面spring mvc也讲过参数重命名的情况,不过那是涉及到前后端交互的,而这个,完全就是我们后端要写的,那还搞啥重命名,所以虽然可以用,但不建议用。
但是这种写法也可能存在,跟技术更迭有关,反正我们要知道,要看得懂这种写法!
🌵增
接口写法

这里的返回值是Integer类型,就是代表增加的行数嘛。
测试


正确。
🌵删
接口写法

测试


测试成功!
🌵改
接口写法

测试


测试成功!
然后如果我们给传的参数旁加个@Param注解呢,试试看,
接口写法,

测试


结果发现,报错了,是我们传递的username没找到,所以我们有理由怀疑,@Param注解加完之后,#{}这种写法取值不到,然后我们只改一下接口写法,

测试

更新成功,所以当加上了@Param注解之后,不能写成类似于#{id}的样子,而是要写成#{重命名之后的类名.id}才可以成功绑定。
🌵获取自增Id-@Options注解
接口写法

这个@Options注解,keyProperty参数,是要从你插入成功之后,拿到你刚插入的字段值,userGneratedKeys参数呢,它为true代表数据库里id字段是个自增的,必须是个自增的字段,为false,代表你自己在查数据库之前,已经设置了id属性,可是一般不这么做,一般设为true。
可能有人要问,为啥要这样获取id,为啥不直接再查一遍数据库,对的,问题就出在这,你想吧,
你能查一遍的东西,你为啥还要查两边,就算你勤快,但你代码量是不是增加了,还不如直接一个@Options注解来的舒服。
测试,


测试成功,返回id。
🌵遗留问题
上面最开始的时候,我们发现当java实体类的属性名称和数据库的字段名称不一致的时候,我们用mybatis执行sql语句时,数据库的那个字段会赋值不上,那我们咋解决这种问题呢,
其实有3种解决办法,
1.起别名
2.结果映射
3.开启驼峰命名
🍀起别名:

我们发现当使用as的时候,返回的视图的字段是deleteFlag,这说明我们这样写,返回的视图可以和java的实体类映射上啊,这问题不久解决了嘛。
接口写法

测试,


我们发现全部映射成功,解决了我们映射缺失的问题。
🍀结果映射
@Results注解

按住ctrl点击,进来

两个属性,一个id,一个@Result的注解数组,再ctrl点击@Result注解,进来

里面是一些属性,有行(要映射的数据库的字段),属性(要映射的java实体类的属性)等等。
那咋用呢?
接口写法,

测试


全部拿到了,结果正确。
但是吧,我们@Results注解里不是还有一个id属性嘛,我们试着把它用上,


上面@Results注解里我们添加了id,也就是把那个查询映射起了个别名,叫BaseMap,
然后我们用了个新注解@ResultMap,然后传入BaseMap,
测试,


全部也都映射上了,所以,大家啥时候用@ResultMap,大家能想到得过去就行。
🍀开启驼峰命名
我们再yml文件里配置一下驼峰自动转化

接口还是原来得写法

测试


发现我们没有做任何处理,加上这个yml配置文件,就自动帮我们处理好了字段和属性得映射问题,虽然是这样子的,但我想说的是,数据库的字段如果是delete_flag,java属性是deleteFlag,
这个yml配置文件呢,会帮我们,把返回的视图里的delete_flag字段某种意义上处理逻辑就是,将_下划线去掉,下划线后面的首字母大写,然后就能和java属性一一对应上了。
🌵MyBatis XML配置文件
上面我们写的都是用注解的方式,写sql语句,接下来这一种,就是用XML的方式来写我们的sql语句了。
这种写法,需要我们在resource包底下,再创建个mapper包,这个mapper包名你可以自定义名称,不一定要叫mapper包,然后我们在mapper包底下选这个。


最后创建成功,它自动写了一些代码,如下,

我们需要先配置一下XML文件,

新增的是mapper-locations: classpath:/mapper/**.xml

mapper-locations: classpath:/mapper/**.xml
classpath代表resources包名,然后是mapper包名,最后是xml文件,我这里的**代表就是创建的xml名字随便。
🌵用XML文件简单写个sql语句

我们先在mapper包底下,创建个UserInfoMapperXML接口,里面是,

和用注解写的步骤差不多,也是需要创建个接口,交给spring管理,但我们的sql语句就不再通过在接口抽象方法上加注解了,而是,

而是在我们创建的xml文件里写,但是,我么开始创建的xml文件里,那个namespace是空的,它表示要和哪个接口进行关联。所以我们填
com.example.mybatistext.mapperc.UserInfoMapperXML
也就是
UserInfoMapperXML接口
为了方便我们写代码,这里我们装下面这个插件

效果:装了这个插件之后,我们就可以通过点击左边的小鸟图标,来对XML文件和接口之间进行跳转操作了,而且这个插件还会帮我们检查XML文件是否有错误啥的,反正大家就装上即可,非常好用。
接口写法

对应的xml

这里我给大家说下,这些参数是啥意思,首先,namespace表示关联的是哪个接口,然后select查询语句的id表示是哪个方法,因为知道了是哪个方法,它好把从数据库里查询的结果映射到具体的方法返回值里去,resultType表示查询出来的都是啥类型的,也不能这么讲,是让查询结果,给我转化成某某类型的java语法格式。
测试,


成功返回结果,而且全都映射上了,这是因为我们前面在yml文件里已经配置了驼峰自动转化,
如下,

分享一个好用的快捷键,你假如在接口里写了个抽象方法,你先选中方法名,然后你按住ALT键和ENTER键就会出现下面这个

然后你点击最上面的这个,他就会自动生成

xml格式的部分写法,而且还自动识别出我方法名getUserInfoById的目的是:将要进行查询操作,所以就是select标签(我这样叫的,大家不必认真讲究说,要读成啥,咋表示)
🌵查
🍀传递一个参数
接口写法

对应的xml

测试

结果

测试成功!
🍀传递多个参数
接口写法

对应的xml

测试

结果

测试成功,返回zhangsan数据行!
🍀参数重命名
接口写法

对应的xml

测试


测试成功!
🌵增
接口写法

对应的xml

需要注意的是,我们的insert语句,不用写resultType等于啥类型,因为这是插入语句,返回的是插入了几条数据。
测试


结果正确,
获取自增Id
前面注解的方式,

接口写法

对应的xml

测试

结果

成功获取到了,自增id,也是一次就完成了插入,和查询,这两个步骤。
🌵删
接口写法

对应的xml

测试

结果

其实只有查,才在xml里加resultType,其它的都是默认Integer返回。
🌵改
接口写法

对应的xml

测试

结果

更新成功!
🌵遗留问题
xml也有这个问题,我们发现当java实体类的属性名称和数据库的字段名称不一致的时候,我们用mybatis执行sql语句时,数据库的那个字段会赋值不上,那我们咋解决这种问题呢,
1.起别名
2.结果映射
3.开启驼峰命名
🍀起别名
在对应的xml文件里,通过as给字段起个别名,这个不多讲。
🍀结果映射
接口写法

对应的xml

简单介绍一下这个resultMap,id就是你给这个模板起的名字,type就是要映射的类型,
里面的这个id就是必须要这样写的!然后result就是要映射的字段和属性的名字了。
先定义"映射模板",然后用这个模板,用resultMap等于模板的id就行

测试

结果

映射成功!
🍀开启驼峰命名
也还是和用注解的方式一样,在yml文件里加行代码就行。

完结了,写了一下午,有点脑海风暴哈哈