Mybatis笔记

MyBatis笔记

0. 概述

Mybatis是一个优秀的基于Java的持久层框架,它内部封装了jdbc,使开发者只需要关注sql语句本身,而不需要花费精力去处理加载驱动、创建连接、创建 statement等繁杂的过程。

官方网站https://mybatis.org/mybatis-3/zh/index.html

Mybatis通过xml或注解的方式将要执行的各种statement配置起来,并通过Java对象和statementsql的动态参数进行映射生成最终执行的 sql语句,最后由 Mybatis 框架执行 sql并将结果映射为 java 对象并 返回。

1. 配置文件

1. 主配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<?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>
<!--引入外部的properties文件,指定一些属性值-->
<properties resource="jdbcConfig.properties"></properties>
<!--取类的别名-->
<typeAliases>
<typeAlias type="com.billychen.domain.User" alias="User"></typeAlias>
<typeAlias type="com.billychen.domain.Account" alias="Account"></typeAlias>
<!--以下是批量别名方式,直接给出扫描包下的所有类,别名为类名-->
<package name="com.billychen.domain"/>
</typeAliases>

<!--配置环境-->
<environments default="mysql">
<!--配置mysql环境-->
<environment id="mysql">
<!--配置事务类型-->
<transactionManager type="JDBC"></transactionManager>
<!--配置数据源(连接池)-->
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>

<mappers>
<!--<mapper resource="com/billychen/dao/IUserDao.xml"></mapper>-->
<!--指定dao接口所在的包,不需要再写mapper标签了-->
<package name="com.billychen.dao"></package>
</mappers>
</configuration>

2.和Dao类对应的XML文件

此处给出一个例子,给出IUserDao.javaIUserDao.xml文件

以下是Java代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public interface IUserDao {
/**
* 查询所有,同时获取到用户的所有账户
* @return
*/
List<User> findAll();

/**
* 根据id查询用户
* @param id
* @return
*/
User findById(Integer id);
}

以下是对应的配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<?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.billychen.dao.IUserDao">


<!--resultMap标签用于实体类属性名和列名的对应-->
<!--如果使用resultMap 之后的resultType也要改为resultType-->
<!--<resultMap id="userMap" type="com.billychen.domain.User">-->
<!--</resultMap>-->
<resultMap id="userAccountMap" type="User">
<id property="id" column="id"></id>
<result property="username" column="username"></result>
<result property="birthday" column="birthday"></result>
<result property="sex" column="sex"></result>
<result property="address" column="address"></result>
<!--配置User对象中accounts集合的映射-->
<!--ofType是集合中元素的类型-->
<!--一对一用association,一对多用collection-->
<collection property="accounts" ofType="Account">
<id property="id" column="aid"></id>
<result property="uid" column="UID"></result>
<result property="money" column="MONEY"></result>
</collection>
</resultMap>

<select id="findAll" resultMap="userAccountMap">
select user.*,account.ID as aid,account.UID,account.MONEY from user left outer join account on account.UID=user.id
</select>

<select id="findById" resultType="com.billychen.domain.User" parameterType="java.lang.Integer">
select * from user where id=#{id};
</select>
</mapper>

3. 延迟加载

查询账户(Account)信息并且关联查询用户(User)信息。如果先查询账户(Account)信息即可满足要 求,当我们需要查询用户(User)信息时再查询用户(User)信息。把对用户(User)信息的按需去查询就是延迟加载。

比如,在查询账户时,需要连带查询其所属的用户。如果使用延迟加载,那么在需要用到用户的时候才进行查询。具体的配置在配置文件association标签中修改如下:

1
<association property="user" javaType="User" select="com.billychen.dao.IUserDao.findById"     column="uid">   </association>

其含义是,根据用户的uid这一列的值,去查询所属账户的id

为了使延迟加载生效,还需要在主配置文件中配置

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

4. 一级缓存和二级缓存

1. 一级缓存

一级缓存是 SqlSession 范围的缓存,当调用 SqlSession 的修改,添加,删除,commit()close()等方法时,就会清空一级缓存

比如:

第一次发起查询用户 id 为 1 的用户信息,先去找缓存中是否有 id 为 1 的用户信息,如果没有,从数据库查询用户信息。

得到用户信息,将用户信息存储到一级缓存中。

如果 sqlSession 去执行 commit 操作(执行插入、更新、删除),清空 SqlSession 中的一级缓存,这样 做的目的为了让缓存中存储的是最新的信息,避免脏读。 第二次发起查询用户 id 为 1

的用户信息,先去找缓存中是否有 id 为 1 的用户信息,缓存中有,直接从缓存 中获取用户信息。

2. 二级缓存

二级缓存是 mapper 映射级别的缓存,多个 SqlSession 去操作同一个 Mapper 映射的 sql 语句,多个 SqlSession 可以共用二级缓存,二级缓存是跨 SqlSession 的。

开启二级缓存:

  1. SqlMapConfig.xml中开启
    1
    2
    3
    4
    <settings> 
    <!-- 开启二级缓存的支持 -->
    <setting name="cacheEnabled" value="true"/>
    </settings>
  2. 配置响应的mapper文件
    1
    2
    3
    4
    <mapper namespace="com.itheima.dao.IUserDao">
    <!-- 开启二级缓存的支持 -->
    <cache></cache>
    </mapper>
  3. 配置statement上的useCache属性
    1
    2
    3
    <select id="findById" resultType="user" parameterType="int" useCache="true">  
    select * from user where id = #{uid}
    </select>