MyBatis 笔记

1. 配置

获取SqlSessionFactory对象

resources 文件夹下新建mybatis-config.xml配置文件,内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"></transactionManager>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://127.0.0.1:3316/mybatis?useSSL=true&amp;useUnicode=true&amp;characterEncoding=UTF-8"/>
<property name="username" value="mybatis"/>
<property name="password" value="yy123456"/>
</dataSource>
</environment>
</environments>
</configuration>

代码中初始化获取SqlSessionFactory对象:

1
2
3
4
5
6
7
8
9
10

try {
// 获取SqlSessionFactory对象
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
}

从SqlSessionFactory中获取SqlSession:

1
2


常见错误

  1. org.apache.ibatis.binding.BindingException: Type interface cn.geekhall.dao.UserMapper is not known to the MapperRegistry.

大多数原因都是应为没有添加mappers或者mapper配置的不对,添加即可:

1
2
3
<mappers>
<mapper class="cn.geekhall.dao.UserMapper"/>
</mappers>

配置解析

核心配置文件:mybatis-config.xml

  • configuration(配置)
  • properties(属性)
  • settings(设置)
  • typeAliases(类型别名)
1
2
3
4
5
6
<!--    类型别名是为Java类型设置一个短的名字,只和XML配置有关,存在的意义仅在于用来减少类完全限定名的冗余-->
<typeAliases>
<typeAlias type="cn.geekhall.pojo.User" alias="User"/>
<!-- 也可以指定一个包名, MyBatis会在包名下面搜索需要的JavaBean。-->
<package name="cn.geekhall.pojo"/>
</typeAliases>

也可以使用注解来定义别名

1
2
@Alias("use")
public class User {}
  • typeHandlers(类型处理器)
  • objectFactory(对象工厂)
  • plugins(插件)
  • environments(环境配置)
  • environment(环境变量)
  • transactionManager(事务管理器)
  • dataSource(数据源)
  • databaseIdProvider(数据库厂商标识)
  • mappers(映射器)

日志

注意配置文件中的logImpl和STDOUT_LOGGING必须完全正确才可以,否则配置会出错不生效。

1
2
3
4
<!-- mybatis 日志功能  -->
<settings>
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
  • STDOUT_LOGGING : 标准日志工厂实现

使用Log4j

分页

Mybatis默认分页

使用RowBounds实现分页

使用注解开发

1
2
3
4
5
@Select("select * from user")
List<User> getUserList();

@Select("select * from user where id = #{uid}")
User getUserById(@Param("uid") int id);

配置mybatis-config.xml绑定接口

1
2
3
<mappers>
<mapper class="cn.geekhall.dao.UserMapper"/>
</mappers>

@Param() 注解

  • 基本类型的参数或者String类型,需要加上
  • 引用类型不需要加
  • 如果只有一个基本类型的话可以忽略,但是建议都加上
  • SQL中使用的就是@Param中设定的属性名

关于#{} 和 ${}

{} 可以防止SQL注入,${}不可以

Lombok

常用注解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
@Getter and @Setter
@FieldNameConstants
@ToString
@EqualsAndHashCode
@AllArgsConstructor, @RequiredArgsConstructor and @NoArgsConstructor
@Log, @Log4j, @Log4j2, @Slf4j, @XSlf4j, @CommonsLog, @JBossLog, @Flogger, @CustomLog
@Data
@Builder
@SuperBuilder
@Singular
@Delegate
@Value
@Accessors
@Wither
@With
@SneakyThrows
@val
@var
experimental @var
@UtilityClass

Lombok config system
Code inspections
Refactoring actions (lombok and delombok)

一对多和多对一

  1. 关联 - association (多对一)
  2. 集合 - collection (一对多)
  3. JavaType & ofType
    • JavaType用来制定实体类中的属性的类型
    • ofType用来指定映射到List或者集合中的pojo的类型,(范型中的约束类型)

动态SQL

使用绑定变量根据不同的条件生成不同的SQL

  • if
1
2
3
4
5
6
7
8
9
<select id="queryBlogIF" parameterType="map" resultType="blog">
select * from mybatis.blog where 1=1
<if test="title != null">
and title = #{title}
</if>
<if test="author != null">
and author = #{author}
</if>
</select>
  • where

where 标签只会在至少有一个子元素的条件返回SQL子句的情况下才去插入WHERE子句。例如,上面的if可以不用where 1=1而改写为

1
2
3
4
5
6
7
8
9
10
11
<select id="queryBlogIF" parameterType="map" resultType="blog">
select * from mybatis.blog
<where>
<if test="title != null">
and title = #{title}
</if>
<if test="author != null">
and author = #{author}
</if>
</where>
</select>
  • choose

choose有点类似与java中的switch和case语句。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<select id="queryBlogChoose" parameterType="map" resultType="blog">
select * from mybatis.blog
<where>
<choose>
<when test="title != null">
title = #{title}
</when>
<when test="author != null">
and author = #{author}
</when>
<otherwise>
and views = #{views}
</otherwise>
</choose>
</where>
</select>
  • set

set语句会动态包含需要更新的列,而舍去其他的,同时会删除无关的逗号。

1
2
3
4
5
6
7
8
9
10
11
12
<update id="updateBlog" parameterType="map">
update mybatis.blog
<set>
<if test="title != null">
title = #{title},
</if>
<if test="author != null">
author = #{author}
</if>
</set>
where id = #{id}
</update>
  • foreach
1
select * from user where 1=1 and (id=1 or id=2 or id=3)

变成

1
2
3
4
<foreach item="item" index="index" collection="list"
open="(" separator="or" close=")">
#{item}
</foreach>

动态SQL的一个常用操作需求是对一个集合进行遍历,通常是在构建IN条件语句的时候。

1
2
3
4
5
6
7
8
9
<select id="selectPostIn" resultType="domain.blog.Post">
select *
from post p
where id in
<foreach item="item" index="index" collection="list"
open="(" separator="," close=")">
#{item}
</foreach>
</select>
  • sql片段

使用sql标签抽取公共的部分

1
2
3
4
5
6
7
8
<sql id="if-title-author">
<if test="title != null">
title = #{title}
</if>
<if test="author != null">
and author = #{author}
</if>
</sql>

在需要使用的地方使用include标签引用即可。

1
2
3
4
5
6
<select id="queryBlogIF2" parameterType="map" resultType="blog">
select * from mybatis.blog
<where>
<include refid="if-title-author"/>
</where>
</select>

MySQL面试高频

  • MySQL引擎
  • InnoDB底层原理
  • 索引
  • 索引优化

缓存

  • 映射语句文件中所有select语句的结果将会被缓存;
  • 映射语句文件中所有insert、update和delete语句将会刷新缓存;
  • 缓存会默认使用最近最少使用算法(LRU,Least Recently Used)算法来清除不需要的缓存。
  • 缓存会不定时进行刷新。
  • 缓存会保存列表或者对象的1024个引用。
  • 一级缓存(本地的会话缓存)默认开启的,只在sqlsession有效。

开启全局缓存:

1
2
3
<settings>
<setting name="cacheEnabled" value="true"/>
</settings>

在需要使用二级缓存的mapper.xml文件中开启,也可以自定义一些参数。

1
2
3
<mapper namespace="sample">
<cache/>
</mapper>