MyBatis事务、延迟加载、缓存、注解

2024/1/12 MyBatis框架

# 1、事务

MyBatis是一个独立的持久层框架,它本身不提供事务管理的功能。但是,MyBatis可以与Spring框架集成,利用Spring的事务管理功能来管理数据库事务。

# 1.1、事务原理

事务我们在Spring章节中已经讲过了,可以参考:Spring事务详解

# 1.2、MyBatis开启事务

  • 增加Spring事务依赖
<!--  spring事务  -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-tx</artifactId>
    <version>5.2.7.RELEASE</version>
</dependency>
1
2
3
4
5
6
  • MyBatisConfig配置将数据源给Spring事务管理器管理
@Bean
public TransactionManager getTrans(DataSource dataSource){
    DataSourceTransactionManager trans =  new DataSourceTransactionManager();
    //设置数据源
    trans.setDataSource(dataSource);
    return trans;
}
1
2
3
4
5
6
7
  • 使用XML方式配置,效果同上
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
         http://www.springframework.org/schema/context
         http://www.springframework.org/schema/context/spring-context.xsd
          http://www.springframework.org/schema/tx
          http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
    
    <!--连接数据库这里读取的是配置文件-->
    <context:property-placeholder location="jdbc.properties"/>
    <!--连接池-->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="${database.driver}"/>
        <property name="url" value="${database.url}"/>
        <property name="username" value="${database.username}"/>
        <property name="password" value="${database.password}"/>
    </bean>

    <!--事务整合-->
    <!-- 配置事务管理器 -->
    <bean id="dataSourceTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>
    <!--事务属性-->
    <tx:advice id="txAdvice" transaction-manager="dataSourceTransactionManager">
        <tx:attributes>
            <tx:method name="Query" isolation="DEFAULT"/>
        </tx:attributes>
    </tx:advice>

</beans>
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

# 2、延迟加载

MyBatis的延迟加载是指在需要用到数据的时候进行加载,不需要用到数据就不进行加载。

延迟加载的原理

  • 当查询主记录时,相关的关联记录并不会立即加载。
  • 当访问这些关联记录时,MyBatis 会触发加载。

MyBatis开启延迟加载

<?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">
<!--mybatis核心配置文件-->
<configuration>

    <settings>
        <!-- 开启延迟加载 -->
        <setting name="lazyLoadingEnabled" value="true"/>
    </settings>
</configuration>
1
2
3
4
5
6
7
8
9
10
11
12

# 3、缓存

# 3.1、缓存特性

  • MyBatis缓存是将查询的数据存在于内存中的临时数据
  • 减少和数据库交互的次数,提高执行力效率
  • 适用于缓存的数据:经常查询的数据、不经常改变的数据、数据的正确与否对最终结果影响不大的

# 3.2、一级缓存

  • 一级缓存是MyBatis中SqlSession对象的缓存
  • 当我们执行查询之后,查询的结果会同时存入得到SqlSession大为我们提供的一块区域中。
  • 该区域是一个Map。
  • 当我们再次查询同样的数据,MyBatis会先去SqlSession中查询是否有,有的话直接拿出来用。
  • SqlSession销毁时,一级缓存也就消失了。
  • 内存地址时一致的 那么就说明了第二次查询使用的是缓存。
  • 可通过sqlSession.clearCache()清空一级缓存。
  • MyBatis的一级缓存当调用SqlSession的修改,添加,删除,commit(),close() 等方法时就会自动清空缓存。
  • MyBatis 的一级缓存是默认开启的。

# 3.3、二级缓存

  • 二级缓存是MyBatis中SqlSessionFactory对象的缓存(工厂的缓存)。
  • 同一个SqlSessionFactory创建出来的多个SqlSession对象,共享同一个二级缓存
  • 二级缓存中存放的数据,而不是对象,因此使用 == 比较对象的内存的地址是false

开启二级缓存有三种情况

  • 全局开启,通过核心配置
<?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">
<!--mybatis核心配置文件-->
<configuration>

    <settings>
        <!-- 开启二级缓存 -->
        <setting name="cacheEnabled" value="true"/>
    </settings>
</configuration>
1
2
3
4
5
6
7
8
9
10
11
12
  • 当前的映射文件支持二级缓存

在UserMapper.xml中加入<cache></cache>

<?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">
<!--namespace-绑定一个对应dao/mapper接口-->
<mapper namespace="com.xygalaxy.mapper.UserMapper">
    <!--当前映射文件开启二级缓存-->
   <cache></cache>
</mapper>
1
2
3
4
5
6
7
8
9
  • 当前的SQL操作支持缓存
<select id="getUserList" resultType="com.xygalaxy.pojo.UserPO" useCache="true" flushCache="true">
    select * from user
</select>
1
2
3

  • useCache="true"表示当前查询开启二级缓存
  • flushCache的默认值是false,表示任何时候语句被调用,都不会去清空本地缓存和二级缓存。

# 4、注解

对于不复杂的SQL时,创建Mapper.xml映射文件显得很麻烦臃肿,所以MyBatis还提供了注解方式。在前面的章节我们也有用过不少。

# 4.1、@Select

@Mapper
@CacheNamespace
public interface UserMapper {

    @Select("select * from user where username like CONCAT('%', #{arg0}, '%') and email like CONCAT('%', #{arg1}, '%')")
    List<UserPO> selectUserMultiparameter(String name,String email);

}
1
2
3
4
5
6
7
8

# 4.2、@Insert

@Insert("insert into user(id,username,password,email) values(#{id},#{username},#{password},#{email})")
@SelectKey(statement="select if(max(id) is null, 1, max(id) +1) as id from user", keyProperty="id", before=false, resultType=int.class)
int saveUser(UserPO userPO);
1
2
3

# 4.3、@Update

@Update({"<script>",
    "update user",
    "  <set>",
    "    <if test='username != null'>username=#{username},</if>",
    "    <if test='password != null'>password=#{password},</if>",
    "    <if test='email != null'>email=#{email},</if>",
    "  </set>",
    "where id=#{id}",
    "</script>"})
void updateUserById(UserPO userPO);
1
2
3
4
5
6
7
8
9
10

# 4.4、@Delete

@Delete("delete from user where id = #{id}")
int deleteUserById(int id);
1
2

# 4.4、@Results

当结果和PO对象不一致时,需要使用@Results注解来映射它们。

@Select("select * from user")
/*用了Results注解的id属性后,在别的地方 直接用id名即可
 * 例如 @ResultMap(value={userMap})
 **/
@Results(id="userMap",value = {
    // 如果id为true表示 该行设置的是主键
    @Result(id = true,property = "id",column = "id"),
    @Result(property = "name",column = "name"),
    @Result(property = "password",column = "password")
})
List<UserPO> selectAllUser();
1
2
3
4
5
6
7
8
9
10
11

# 4.5、@CacheNamespace

@CacheNamespace 用于为 MyBatis 的 Mapper 接口启用缓存功能。通过使用这个注解,你可以将 MyBatis 的查询结果缓存起来,从而提高应用程序的性能。

@CacheNamespace
public interface UserMapper {

}
1
2
3
4

# 4.6、@Mapper

@Mapper 是 MyBatis-Spring 集成中的一个注解,用于将接口声明为 MyBatis 的 Mapper。通过使用这个注解,你可以将 MyBatis 的映射文件和接口绑定在一起,并自动将 SQL 语句映射到接口的方法上。

@Mapper
public interface UserMapper {

}
1
2
3
4