文章目录

一、概念

**Mybatis简介:**Mybatis是一款优秀的基于ORM的半自动,轻量级持久层框架,他支持定制化SQL、存储过程及高级映射。

  1. ORM:全称Object Relation Mapping:对象关系映射的缩写(将程序员直接操作数据库的工作转换为操作对象,ORM框架将这些面向对象的操作转换为底层的SQL操作)
  2. 半自动:全自动框架程序员将失去对SQL进行优化的权利,半自动支持我们去编写优化SQL
  3. 轻量级:Mybatis在启动时需要的资源较少

**Mybatis优势:**Mybatis是一个半自动化的持久层框架。对开发人员而言,核心SQL还需要自己优化,SQL和java编码分开,功能边界清晰,一个专注业务一个专注数据。

二、快速入门

Mybatis官网地址

1.开发步骤

  1. 添加Mybatis依赖
  2. 创建User数据表
  3. 编写User实体类
  4. 编写映射配置文件UserMapper.xml
  5. 编写核心配置文件sqlMapConfig.xml
  6. 编写测试类

2.环境搭建

2.1.导入Mybatis的坐标和其他坐标

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.encoding>UTF-8</maven.compiler.encoding>
<java.version>1.8</java.version>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties> <dependencies>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.5</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.17</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>

2.2.创建User表

2.3.编写实体

public class User {
private Integer id;
private String username;
//省略get,set方法
}

2.4.编写UserMapper配置文件

<?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="user">
<!--namespace:名称空间:与ID组成SQL的唯一标识-->
<!--查询用户-->
<select id="findAll" resultType="com.myf.pojo.User">
select * from user
</select>
<!--添加用户-->
<select id="saveUser" parameterType="com.myf.pojo.User">
insert into user values (#{id},#{username})
</select>
<!--修改用户-->
<update id="updateUser" parameterType="com.myf.pojo.User">
/*参数对应的是实体类中get方法方法名首字母小写获得的*/
update user set username=#{username} where id = #{id}
</update>
<!--删除用户-->
<delete id="deleteUser" parameterType="java.lang.Integer">
delete from user where id = #{id}
</delete>
</mapper>

2.5.编写核心配置文件

<?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运行环境-->
<environments default="development">
<!--生产环境-->
<environment id="">
<transactionManager type=""></transactionManager>
<dataSource type=""></dataSource>
</environment>
<!--开发环境-->
<environment id="development">
<!--表示当前事务交由JDBC进行管理-->
<transactionManager type="JDBC"></transactionManager>
<!--表示使用mybatis提供的连接池,UNPOOLED代表不使用连接池-->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql:///zdy_mybatis"/>
<property name="username" value="root"/>
<property name="password" value="******"/>
</dataSource>
</environment>
</environments> <!--引入映射配置文件-->
<mappers>
<mapper resource="UserMapper.xml"></mapper>
</mappers>
</configuration>

2.6.编写测试代码

@Test
public void test1() throws IOException {
//1.Resources工具类,配置文件的加载,把配置文件加载成字节输入流
InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");
//2.解析配置文件,并创建了sqlSessionFactory对象
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
//3.生产sqlSession
//默认开启一个事务但事务不会自动提交,需要手动提交事务。可以设置.openSession(true);自动提交事务
SqlSession sqlSession = sqlSessionFactory.openSession();
//4.sqlSession调用方法:查询所有selectList,查询单个selectOne,添加insert,修改update,删除delete
List<Object> objects = sqlSession.selectList("user.findAll");
for (Object o : objects) {
System.out.println(o);
}
}

三、Mybatis核心配置文件分析

Mybatis核心配置文件层级关系

1.Mybatis常用标签

1.1 environments标签

数据库环境配置,支持多环境配置

transactionManager类型有两种

  1. JDBC:这个配置就是直接使用了JDBC的提交和回滚,它依赖于从数据源得到的连接来管理事务作用域。
  2. MANAGER:不会提交和回滚一个连接,而是让容器来管理实务的整个生命周期。

dataSource数据源*类型有三种

  1. UNPOOLED:每次请求获取新的连接结束后关闭连接。
  2. POOLED:表示使用连接池
  3. JNDI:JNDI—数据源的这个实现是为了与EJB或应用服务器这样的容器一起使用,这些容器可以集中或外部配置数据源,并在JNDI上下文中放置对数据源的引用。(不重要)

1.2 mappers标签

Java doesn’t really provide any good means of auto-discovery in this regard, so the best way to do it is to simply tell MyBatis where to find the mapping files.

Java实际上并没有提供任何好的自动发现方法,所以最好的方法是简单地告诉MyBatis在哪里找到映射文件。

<mappers>
<!-- Using classpath relative resources -->
<!-- 使用相对于类路径引用 -->
<mapper resource="org/mybatis/builder/AuthorMapper.xml"/>
<!-- Using url fully qualified paths -->
<!-- 使用完全限定资源定位符 -->
<mapper url="file:///var/mappers/AuthorMapper.xml"/>
<!-- Using mapper interface classes -->
<!-- 使用类的完全限定名 -->
<mapper class="org.mybatis.builder.AuthorMapper"/>
<!-- Register all interfaces in a package as mappers -->
<!-- 将包内的映射器接口实现全部注册为映射器 -->
<package name="org.mybatis.builder"/>
</mappers>

2.配置文件深入

2.1 Properties标签

习惯将数据源的配置信息单独抽取成一个properties文件

编写jdbc.properties

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql:///zdy_mybatis
jdbc.username=root
jdbc.password=110110110

sqlMapConfig引入jdbc.properties

<properties resource="jdbc.properties"></properties>

<!--dataSource前后省略了environments标签-->
<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>

测试代码正常执行,成功读取到了配置信息

2.2 typeAliases标签

为java类型设置短的别名

<typeAliases>
<!--给单独的实体起别名-->
<typeAlias type="com.myf.pojo.User" alias="user"></typeAlias>
<!--批量起别名,别名为类名:别名不区分大小写-->
<package name="com.myf.pojo"/>
</typeAliases>

常用基本类型别名配置

integer Integer
double Double
float Float
boolean Boolean
。。。。 。。。。

3. mapper.xml

3.1 动态SQL之if

<!--多条件组合查询:演示If-->
<select id="findByCondition" parameterType="user" resultType="user">
select * from USER
<where>
<if test="id != null">
and id = #{id}
</if>
<if test="username != null and username!=''">
and username = #{username}
</if>
</where>
</select>

3.2 动态SQL之forEach

<!--多值查询:演示forEach-->
<select id="findByIds" parameterType="list" resultType="user">
select * from user
<where>
/*collection:array数组,list集合,open开始,close结束,item元素,separator分割*/
<foreach collection="array" open="id in (" close=")" item="id" separator=",">
#{id}
</foreach>
</where>
</select>

3.3 sql映射抽取

<!--抽取SQL片段-->
<sql id="selectUser">
select * from USER
</sql> <select id="findAll" resultType="user">
<include refid="selectUser"></include>
</select>

四.Mybatis的Dao层实现

1. 传统开发方式

编写接口

public interface UserDao {
//查询所有用户
public List<User> findAll() throws IOException;
}

编写实现类

public class UserDaoImpl implements UserDao {
@Override
public List<User> findAll() throws IOException {
//返回文件流
InputStream resourceAsSteam = Resources.getResourceAsStream("sqlMapConfig.xml");
//构建SqlSessionFactory对象
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsSteam);
SqlSession sqlSession = sqlSessionFactory.openSession();
List<User> list = sqlSession.selectList("user.findAll");
return list;
}
}

编写测试类

@Test
public void test5() throws IOException {
UserDao userDao = new UserDaoImpl();
List<User> users = userDao.findAll();
for (User o : users) {
System.out.println(o);
}
}

2. 代理开发方式

只需要编写dao接口

mapper接口需要遵循以下规范

  1. Mapper.xml文件中的namespace与mapper接口的全限定名相同。
  2. Mapper接口方法名与Mapper.xml中定义的每个SQL的parameterType类型相同。
  3. Mapper接口方法的输入参数类型和mapper.xml中定义的每个parameterType的类型相同。
  4. Mapper接口方法的返回值类型和Mapper.xml中定义的每个resultType的类型相同。

修改接口和配置文件的对应关系

测试类

@Test
public void test5() throws IOException {
InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
UserDao mapper = sqlSession.getMapper(UserDao.class);
List<User> users = mapper.findAll();
for (User user : users) {
System.out.println(user);
}
}

五、Mybatis复杂映射开发

查询多个表,resultType(自动按照字段名和属性名完成映射封装)不满足需求,使用resultMap手动配置实体属性与表字段的映射关系

1. 一对一查询

查询订单并带出用户信息

编写接口

public interface UserMapper {
//查询订单的同时还查询该订单所属的用户
public List<Order> findOrderAndUser();
}

编写mapper.xml

<?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.myf.mapper.UserMapper"> <resultMap id="orderMap" type="com.myf.pojo.Order">
<result property="id" column="id"></result>
<result property="orderTime" column="orderTime"></result>
<result property="total" column="total"></result>
<result property="uid" column="uid"></result> <association property="user" javaType="com.myf.pojo.User">
<result property="id" column="uid"></result>
<result property="username" column="username"></result>
<result property="password" column="password"></result>
<result property="birthday" column="birthday"></result>
</association>
</resultMap> <!--resultMap手动配置实体属性与表字段的映射关系-->
<select id="findOrderAndUser" resultMap="orderMap">
SELECT * FROM orders o,user u WHERE o.uid = u.id
</select>
</mapper>

编写测试类

public class MybatisTest {
@Test
public void test1() throws IOException {
InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession sqlSession = sqlSessionFactory.openSession(true);
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<Order> orders = mapper.findOrderAndUser();
for (Order order : orders) {
System.out.println(order);
}
}
}

2. 一对多查询

查询出全部用户信息并带出订单信息

XML配置

<resultMap id="userMap" type="com.myf.pojo.User">
<id property="id" column="id"/>
<result property="username" column="username"/>
<result property="password" column="password"/>
<result property="birthday" column="birthday"/> <collection property="orderList" ofType="com.myf.pojo.Order">
<id property="id" column="oid"/>
<result property="orderTime" column="ordertime"/>
<result property="total" column="total"/>
<result property="uid" column="uid"/>
</collection>
</resultMap> <select id="findUserAndOrder" resultMap="userMap">
SELECT
u.*,
o.id oid,
o.ordertime,
o.total,
o.uid
FROM
USER u
LEFT JOIN orders o ON u.id = o.uid
</select>

3. 多对多查询

多对多在数据库中的体现是添加一个用户角色关联表

查询所有用户查询出每个用户关联的角色

<resultMap id="userRoleMap" type="com.myf.pojo.User">
<id property="id" column="id"/>
<result property="username" column="username"/>
<result property="password" column="password"/>
<result property="birthday" column="birthday"/> <collection property="roleList" ofType="com.myf.pojo.Role">
<id property="id" column="sid"/>
<result property="roleName" column="roleName"/>
<result property="roleDesc" column="roleDesc"/>
</collection>
</resultMap> <select id="findUserAndRole" resultMap="userRoleMap">
SELECT
u.*,
sr.id sid,
sr.rolename roleName,
sr.roleDesc roleDesc
FROM
USER u
LEFT JOIN sys_user_role ur ON u.id = ur.userid
LEFT JOIN sys_role sr ON ur.roleid = sr.id
</select>

六、Mybatis注解开发

  • @Insert:实现新增
  • @Update:实现更新
  • @Delete:实现删除
  • @Select:实现查询
  • @Result:实现结果集封装
  • @Results:可以与
  • @Result 一起使用,封装多个结果集
  • @One:实现一对一结果集封装
  • @Many:实现一对多结果集封装

1. 基本注解开发

编写接口

@Insert("insert into user(id,username) values(#{id},#{username})")
public void addUser(User user); @Update("update user set username = #{username} where id = #{id}")
public void updateUser(User user); @Select("select * from user")
public List<User> selectUser(); @Delete("delete from user where id = #{id}")
public void deleteUser(Integer id);

2.复杂映射开发

2.1 一对一查询

查询订单并带出用户信息

@Results({
@Result(property = "id",column = "id"),
@Result(property = "orderTime",column = "orderTime"),
@Result(property = "total",column = "total"),
@Result(property = "user",column = "uid",javaType = User.class,one = @One(select = "com.myf.mapper.UserMapper.findUserById"))
})
@Select("select * from Orders")
public List<Order> findOrderAndUser2();

@One执行的是User的查询

@Select("select * from user where id = #{id}")
public User findUserById(Integer id);

2.2 一对多查询

查询出全部用户信息并带出订单信息

@Results({
@Result(property = "id",column = "id"),
@Result(property = "username",column = "username"),
@Result(property = "password",column = "password"),
@Result(property = "birthday",column = "birthday"),
@Result(property = "orderList",column = "id",javaType = List.class,many = @Many(select = "com.myf.mapper.OrderMapper.findOrderByUid"))
})
@Select("select * from user")
public List<User> findUserAndOrder2();

@Many执行的Order查询是

@Select("select * from orders")
public List<Order> findOrderByUid(Integer id);

2.3 多对多查询

多对多在数据库中的体现是添加一个用户角色关联表

查询所有用户查询出每个用户关联的角色

@Select("select * from user")
@Results({
@Result(property = "id",column = "id"),
@Result(property = "username",column = "username"),
@Result(property = "password",column = "password"),
@Result(property = "birthday",column = "birthday"),
@Result(property = "roleList",column = "id",javaType = List.class,many = @Many(select = "com.myf.mapper.RoleMapper.findRoleByUid"))
})
public List<User> findUserAndRole2();

@Many执行的Role查询是

@Select("select * from sys_role r, sys_user_role ur where r.id = ur.roleid and ur.userid = #{id}")
public List<Role> findRoleByUid(Integer id);

七、Mybatis缓存

缓存就是内存中的数据,对数据库的查询结果的保存,使用缓存,我们可以避免频繁的与数据库尽心交互,进而提高响应速度。

Mybatis也提供了对缓存的支持,分为一级缓存和二级缓存。

  1. 一级缓存是sqlSession级别的缓存。在操作数据库时需要构造sqlSession对象,在对象中有一个数据结构(HashMap)用于存储缓存数据。不同sqlSession之间的缓存数据区域HashMap是互不影响的。
  2. 二级缓存是mapper级别的缓存,多个sqlSession去操作同一个Mapper的sql语句,多个sqlSession可以共用二级缓存,二级缓存是跨sqlSession的。

1.一级缓存

Mybatis中一级缓存默认是开启的

验证一级缓存的存在

@Test
public void firstLevelCache(){
//第一次查询ID为1的用户
User user1 = userMapper.findUserById(1);
//第二次查询ID为1的用户
User user2 = userMapper.findUserById(1);
System.out.println(user1==user2);
}

通过调试日志可知只有第一次访问了数据库,切user1和user2是同一个对象的引用(内存地址相同)

@Test
public void firstLevelCache(){
//第一次查询ID为1的用户
User user1 = userMapper.findUserById(1);
User user = new User();
user.setId(1);
user.setUsername("moyifeng");
userMapper.updateUser(user);
//第二次查询ID为1的用户
User user2 = userMapper.findUserById(1);
System.out.println(user1==user2);
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qsSO88rR-1605459206131)(.\D12__Mybatis相关概念.assets\image-20201115202913954.png)]

通过日志信息可知,在发生增删操作之后,再次发生相同查询会访问数据库

总结

  1. 第一次发起查询用户id为1的用户信息,先去找缓存中是否有id为1的用户信息,如果没有,从数据库查询用户信息,将用户信息存储到一级缓存中。
  2. 如果中建sqlSession执行了增删改操作,则会清空sqlSession中的一级缓存,这样做的目的是为了让缓存中存储的是最新的信息,避免脏读。
  3. 第二次发起查询用户id为1的用户信息,先去找缓存中是否有id为1的用户信息,缓存中有直接从缓存中获取用户信息。

2.一级缓存源码分析

问题:

一级缓存是什么?

一级缓存什么时候创建、一级缓存的工作流程是怎样的?

分析

  1. 首先看代码,sqlSession为创建的执行sql的对象,因此从这作为入口找到clearCache()与缓存相关。
  2. sqlSession是接口找到其实现类DefaultSqlSession。
  3. DefaultSqlSession中clearCache执行的是Executor.clearLocalCache()。
  4. 找到Executor的实现类BaseExecutor。
  5. 看到其执行的第一句话就是PerpetualCache.clear()。
  6. PerpetualCache的clear方法中执行的是this.cache.clear()。看其属性this.cache就是一个HashMap。cache.clear()就是map.clear()
  7. 由以上分析可知,Mybatis一级缓存本质就是一个HashMap实现的。
  8. Mybatis到底是如何创建使用的一级缓存呢,我们想到Mybatis所有的查询都是通过Executor执行的找到他,发现其中还有一个缓存相关接口createCacheKey。
  9. 找到其实现类,其执行的方法就是创建了一个可以唯一确定查询的key,那么什么时候执行的呢,由之前的自定义Mybatis框架我们想到query方法。
  10. 具体看下图

3.二级缓存

二级缓存的原理和一级缓存原理一样,第一次查询,会将数据放入缓存中,然后第二次查询则会直接去缓存中取。但是一级缓存是基于sqlSession的,而二级缓存是是基于mapper的namespace的,也就是说多个sqlSession可以共享一个mapper中的二级缓存区域,并且如果两个mapper的namespace相同,即使是两个mapper,那么这两个mapper中执行sql查询到的数据也将存储在相同的二级缓存区域中。

3.1 开启二级缓存

全局配置文件sqlConfig.xml中

<settings>
<setting name="cacheEnabled" value="true"/>
</settings>

其次在UserMapper.xml文件中开启缓存

<!--开启二级缓存-->
<cache></cache>

注解方式在类上加注解

@CacheNamespace
public interface UserMapper {

3.2 测试效果

@Test
public void secondLevelCache(){
SqlSession sqlSession = sqlSessionFactory.openSession();
SqlSession sqlSession1 = sqlSessionFactory.openSession();
SqlSession sqlSession2 = sqlSessionFactory.openSession(); UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
UserMapper userMapper1 = sqlSession1.getMapper(UserMapper.class);
UserMapper userMapper2 = sqlSession2.getMapper(UserMapper.class); User user = userMapper.findUserById(1);
sqlSession.close();//清空一级缓存
User user1 = userMapper1.findUserById(1); User user2 =new User();
user2.setId(1);
user2.setUsername("moyifeng1");
userMapper2.updateUser(user2);
sqlSession2.commit(); User user11 = userMapper1.findUserById(1);
System.out.println(user==user1);
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ny0MoD8L-1605459206132)(.\D12__Mybatis相关概念.assets\image-20201115222250870.png)]

3.3 其他配置

userCache

单独设置该sql是否禁用二级缓存,在statement中设置useCache=false可以金融当前select语句的二级缓存,默认为true

<select id="selectUserByUserId" useCache="false"resultType="com.myf.pojo.User" parameterType="int">
select * from user where id=#{id}
</select>

注解方式

@Options(useCache = false)
@Select("select * from user")
public List<User> selectUser();

flushCache

在执行增删改操作后刷新缓存,默认是开启的,所以一般不用操作,设置成false则不会刷新缓存,设置方式参考userCache

4. Mybatis使用Redis实现二级缓存

4.1 二级缓存源码概述

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CMfGfBkw-1605459206135)(.\D12__Mybatis相关概念.assets\image-20201115224112362.png)]

不管是Mybatis自己实现的二级缓存还是自定义二级缓存都是实现上方标红的Cache接口。

PerpetualCache是Mybatis的默认实现类,打开该类可以看到其底层数据结构就是HashMap。

前面我们声明使用了二级缓存

@CacheNamespace
public interface UserMapper {

上面的写法其实是下面的缩写

@CacheNamespace(implementation = PerpetualCache.class)
public interface UserMapper {

4.2 二级缓存整合Redis

上面学习了Mybatis自带的二级缓存,但是这个缓存是单服务器工作,无法实现分布式缓存。

为了解决这个问题,就得找一个分布式缓存,专门用来存储缓存数据的,不同的服务器缓存都在这个专门的缓存服务器存取。

这里我们介绍mybatis与redis的整合。

mybatis提供了一个eache接口,如果要实现自己的缓存逻辑,实现cache接口开发即可。

解决Mybatis自带的二级缓存无法实现分布式缓存的问题,我们使用redis分布式缓存,

mybatis提供了一个针对cache接口的redis实现类,该类存在mybatis-redis包中

具体实现步骤

  1. pom文件
<dependency>
<groupId>org.mybatis.caches</groupId>
<artifactId>mybatis-redis</artifactId>
<version>1.0.0-beta2</version>
</dependency>
  1. 配置文件

Mapper.xml

<cache type="org.mybatis.caches.redis.RedisCache" />

注解

@CacheNamespace(implementation = RedisCache.class)
public interface UserMapper {
  1. redis.properties
redis.host=localhost
redis.port=6379
redis.connectionTimeout=5000
redis.password=
redis.database=0
  1. 测试

直接执行之前的二级缓存测试方法,日志效果是相同的(不要忘了打开redis)

@Test
public void secondLevelCache(){
SqlSession sqlSession = sqlSessionFactory.openSession();
SqlSession sqlSession1 = sqlSessionFactory.openSession();
SqlSession sqlSession2 = sqlSessionFactory.openSession(); UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
UserMapper userMapper1 = sqlSession1.getMapper(UserMapper.class);
UserMapper userMapper2 = sqlSession2.getMapper(UserMapper.class); User user = userMapper.findUserById(1);
sqlSession.close();//清空一级缓存
User user1 = userMapper1.findUserById(1); User user2 =new User();
user2.setId(1);
user2.setUsername("moyifeng1");
userMapper2.updateUser(user2);
sqlSession2.commit(); User user11 = userMapper1.findUserById(1);
System.out.println(user==user1);
}

5.redisCache源码分析

  1. RedisCache和普遍实现Mybatis缓存方案大同小异,无非是实现Cache接口并使用jedis操作缓存
  2. RedisCache在mybatis启动的时候,由MyBatis的CacheBuilder创建,创建的方式很简单,就是调用 RedisCache的带有String参数的构造方法,即RedisCache(String id);而在RedisCache的构造方法中, 调用了 RedisConfigu rationBuilder(读取配置文件信息)来创建 RedisConfig 对象,并使用 RedisConfig 来创建JedisPool(Jedis池)。
  3. 另外两个重要的方法就是putObject和getObject,可以知道其就是使用的Redis的Hash来存储的数据。

八、Mybatis插件

Mybatis轻松入门(仅要求会用看着一个就够了,略过源码分析部分即可)的更多相关文章

  1. 入门数据结构与算法,看这一个就够了,知识点+LeetCode实战演练

    本笔记来自拉钩教育300分钟搞定算法面试 算法与数据结构 要掌握一种数据结构,就必须要懂得分析它的优点和缺点. 在考虑是否应当采用一种数据结构去辅助你的算法时,请务必考虑它的优缺点,看看它的缺点是否会 ...

  2. 通过源码分析MyBatis的缓存

    前方高能! 本文内容有点多,通过实际测试例子+源码分析的方式解剖MyBatis缓存的概念,对这方面有兴趣的小伙伴请继续看下去~ MyBatis缓存介绍 首先看一段wiki上关于MyBatis缓存的介绍 ...

  3. 【Netty之旅四】你一定看得懂的Netty客户端启动源码分析!

    前言 前面小飞已经讲解了NIO和Netty服务端启动,这一讲是Client的启动过程. 源码系列的文章依旧还是遵循大白话+画图的风格来讲解,本文Netty源码及以后的文章版本都基于:4.1.22.Fi ...

  4. [源码分析] 从源码入手看 Flink Watermark 之传播过程

    [源码分析] 从源码入手看 Flink Watermark 之传播过程 0x00 摘要 本文将通过源码分析,带领大家熟悉Flink Watermark 之传播过程,顺便也可以对Flink整体逻辑有一个 ...

  5. [源码分析] 从实例和源码入手看 Flink 之广播 Broadcast

    [源码分析] 从实例和源码入手看 Flink 之广播 Broadcast 0x00 摘要 本文将通过源码分析和实例讲解,带领大家熟悉Flink的广播变量机制. 0x01 业务需求 1. 场景需求 对黑 ...

  6. mybatis源码分析:启动过程

    mybatis在开发中作为一个ORM框架使用的比较多,所谓ORM指的是Object Relation Mapping,直译过来就是对象关系映射,这个映射指的是java中的对象和数据库中的记录的映射,也 ...

  7. C++ STL编程轻松入门基础

    C++ STL编程轻松入门基础 1 初识STL:解答一些疑问 1.1 一个最关心的问题:什么是STL 1.2 追根溯源:STL的历史 1.3 千丝万缕的联系 1.4 STL的不同实现版本 2 牛刀小试 ...

  8. JavaScript面向对象轻松入门之封装(demo by ES5、ES6、TypeScript)

    本章默认大家已经看过作者的前一篇文章 <JavaScript面向对象轻松入门之抽象> 为什么要封装? 封装(Encapsulation)就是把对象的内部属性和方法隐藏起来,外部代码访问该对 ...

  9. Java-MyBatis:MyBatis 3 入门

    ylbtech-Java-MyBatis:MyBatis 3 入门 1.返回顶部 1. 入门 安装 要使用 MyBatis, 只需将 mybatis-x.x.x.jar 文件置于 classpath ...

随机推荐

  1. C语言:带参数的宏与函数的区别

    带参数的宏和函数很相似,但有本质上的区别:宏展开仅仅是字符串的替换,不会对表达式进行计算:宏在编译之前就被处理掉了,它没有机会参与编译,也不会占用内存.而函数是一段可以重复使用的代码,会被编译,会给它 ...

  2. Day5 Scanner对象学习.

    Scanner对象 Java.until.Scanner 我们可以通过Scanner类来获取用户的输入. 基本语法: Scanner s = new Scanner (System . in) ; 通 ...

  3. Ubuntu Server连接Wi-Fi

    本文将介绍Ubuntu Server如何通过命令行使用wpa_supplicant连接Wi-Fi 环境 Ubuntu Server 20.04(64位) wpasupplicant 配置 1. 安装 ...

  4. 深入刨析tomcat 之---第3篇 HTTP/1.1 长连接的实现原理

    writedby 张艳涛 长连接是HTTP/1.1的特征之一,1.1出现的原因是因为一个客户请求一个网页,这是一个http请求,这个网页中如果有图片,那么也会变为一个http请求,对于java客户端, ...

  5. [源码解析] 机器学习参数服务器 Paracel (1)-----总体架构

    [源码解析] 机器学习参数服务器 Paracel (1)-----总体架构 目录 [源码解析] 机器学习参数服务器 Paracel (1)-----总体架构 0x00 摘要 0x01使用 1.1 配置 ...

  6. C# WinForm 数据库连接及对数据库的相关操作

    1.首先在App.config配置文件中配置数据库连接字符串: <appSettings> <add key="connectionstring" value=& ...

  7. 冲击BATZ!GitHub近8.3K+的Android进阶指南,面试再也不愁了

    过去十年是移动互联网蓬勃发展的黄金期,相信每个人也都享受到了移动互联网红利,在此期间,移动互联网经历了曙光期.成长期.成熟期.现在来说已经进入饱和期. 依然记得在 2010-2013 年期间,从事移动 ...

  8. GitHub标星8k,字节跳动高工熬夜半月整理的“组件化实战学习手册”,全是精髓!

    前言 什么是组件化? 最初的目的是代码重用,功能相对单一或者独立.在整个系统的代码层次上位于最底层,被其他代码所依赖,所以说组件化是纵向分层. 为什么要使用组件化? 当我们的项目越做越大的时候,有时间 ...

  9. srt文件的时间轴平移处理

    有时srt字幕文件与视频文件的时间不完全吻合,有一个时间差,这就需要对srt文件的时间轴进行平移,具备这个功能的软件很多,比如:Subtitle Tool, subresync, sabbu, Sub ...

  10. Linux 内核预备知识:浅析 offsetof 宏以及新手的所思所想

    最近一头扎进了 Linux 内核的学习中,对于我这样一个没什么 C 语言基础的新生代 Java 农民工来说实在太痛苦了.Linux 内核的学习,需要的基础知识太多太多了:C 语言.汇编语言.数据结构与 ...