介绍
MyBatis是一个支持普通SQL查询、存储过程、高级映射的优秀持久层框架。MyBatis消除了几乎所有的JDBC代码和参数的手工设置以及对结果集的检索封装。MyBatis可以使用简单的XML或注解用于配置和原始映射,将接口和Java的POJO映射成数据库中的记录。
快速入门
使用到Maven+Mybatis+log4j+generator+lombok,最终实现的文件目录结构如下:
pom文件
1 |
|
db.properties:数据库配置文件
1 | #Mysql配置 |
log4j.properties:log4j配置文件
MyBatis 内置日志工厂基于运行时自省机制选择合适的日志工具。它会使用第一个查找得到的工具(优先级从高到低:SLF4J、Apache Commons Logging、Log4j 2、Log4j、JDK logging)。如果一个都未找到,日志功能就会被禁用。
1 | log4j.rootLogger=DEBUG,Console |
mybatis-config.xml:Mybatis配置文件
1 |
|
generatorConfig.xml:Generator配置文件
Mybatis属于半自动ORM,在使用这个框架中,工作量最大的就是书写Mapping的映射文件,由于手动书写很容易出错,可以利用Mybatis-Generator来帮我们自动生成Dao、Model、Mapping相关文件
1 |
|
配置完打开Maven,右键执行Generator
执行完项目下自动生成了3个文件,省去了我们手写:下划线转驼峰的的EMP.java,数据库字段与实体字段映射关系的EMPMapper.xml,一个与EMPMapper.xml匹配的的接口EMPMapper.java
EMP.java:用于存储数据库返回的数据。删除其他不需要代码,使用lombok注解@Data
1 | package com.co.webapp.entity; |
EMPMapper.xml:定义执行的SQL
namespace为EMPMapper.java的路径+类名,id为对应的方法名,namespace和id都必须是全局唯一的,入参和出参类型必须与EMPMapper.java保持一致
注:查询SQL语句结尾不能加分号,匿名块可以
1 |
|
EMPMapper.java:定义与数据库交互接口
1 | package com.co.webapp.mapper; |
MybatisUtil.java:公用的Mybatis工具类,可以减少代码,配置公用
1 | package com.co.webapp.base; |
Test.java:测试
1 | package com.co.webapp; |
执行结果:
参数
以#{userId,mode=IN,jdbcType=INTEGER}举例:
- mode:声明参数方式(IN、OUT、INOUT)
- jdbcType:声明入参类型
- 如果接口入参写了@Param(“userId”)或入参类型为Map、实体等,则可用对应的key做别名
- 如果没写,则可用 #{0} 、 #{1}这样默认顺序声明参数
参数中#{}和${}区别:
- #{}:Mybatis拼装sql时会自动对参数添加单引号’’ ,如传入的参数为123,会变成’123’
- ${}:Mybatis不对参数做任何转换,一般用于传入表名或字段名使用,可能导致SQL注入,使用$需要同时指定属性statementType=”STATEMENT”,开启非预编译模式。
标签
select、insert、update、delete
- parameterType:参数类型,如:实体(com.co.webapp.entity.EMP)、int
- resultType :返回类型,如:实体(com.co.webapp.entity.EMP)、Map、List
- resultMap:返回类型,如果查询出来的列名和实体属性名不一致,可以定义resultMap对数据库字段名和实体属性名指定映射关系。注:resultType 与resultMap 不能并用
1 | <mapper namespace="com.co.webapp.mapper.EMPMapper"> |
if
通常用于WHERE语句中,通过判断参数值来决定是否使用某个查询条件
1 | <update id="updateEMP" parameterType="com.co.webapp.entity.EMP"> |
foreach
主要用于构建in条件,实现在sql中对集合进行迭代,注:如果collection参数为空就无法完成拼接SQL会报错,可以用if来先做是否为空的判断
主要属性:
- collection:类型可以为list、array数组、map
- item:表示集合中每一个元素进行迭代时的别名
- index:指代每次迭代坐标位置
- open:表示语句以什么开始
- separator:表示在每次进行迭代之间以什么符号作为分隔符
- close:表示语句以什么结束
批量查询
1 | //接口 |
批量插入
1 | //接口 |
choose
按顺序判断when中的条件是否成立,如果有一个成立则结束。当choose中所有when的条件都不满则时,则执行 otherwise
1 | //接口 |
where
如果where的标签中有返回值的话,就插入一个”where”
1 | <select id="queryEMP" parameterType="java.util.Map" resultType="com.co.webapp.entity.EMP"> |
set
当在update语句中使用if标签时,如果前面的if没有执行,则或导致逗号多余错误。使用set标签可以自动添加SET 关键字,并且自动剔除追加到条件末尾的不需要用到的逗号
1 | <update id="updateEMP" parameterType="com.co.webapp.entity.EMP"> |
association、collection
两者适用场景:调用一次查询,将表A和表B关联查询出的结果集,分别放入实体A和实体B,允许二层及以上的嵌套查询
association:关联,一对一和多对一查询
1 | //EMP |

collection:聚集,一对多查询
1 | //EMP |

额外:
这种方式用association或collection都可以,这种方式相当于两次查询,性能和效率较低
1 | //EMP |
调用存储过程
传入类型为Map,返回参数reCode和rtMessage会自动封装到map里面
1 | //接口 |

参数模式
STATEMENT(非预编译)、PREPARED(预编译)、CALLABLE。默认使用:PREPARED。
区别:
- STATEMENT: 普通的不带参的查询SQL,支持批量更新,批量删除
- PREPARED: 可变参数的SQL,编译一次多次执行,效率高,安全性好,有效防止Sql注入等问题,支持批量更新,批量删除
- CALLABLE: 继承自PREPARED,支持带参数的SQL操作,支持调用存储过程,提供了对输入参数(IN)/输出参数(OUT)的支持,注:调用存储过程需用此方式