Mybatis轻松入门(仅要求会用看着一个就够了,略过源码分析部分即可)
文章目录
一、概念
**Mybatis简介:**Mybatis是一款优秀的基于ORM的半自动,轻量级持久层框架,他支持定制化SQL、存储过程及高级映射。
- ORM:全称Object Relation Mapping:对象关系映射的缩写(将程序员直接操作数据库的工作转换为操作对象,ORM框架将这些面向对象的操作转换为底层的SQL操作)
- 半自动:全自动框架程序员将失去对SQL进行优化的权利,半自动支持我们去编写优化SQL
- 轻量级:Mybatis在启动时需要的资源较少
**Mybatis优势:**Mybatis是一个半自动化的持久层框架。对开发人员而言,核心SQL还需要自己优化,SQL和java编码分开,功能边界清晰,一个专注业务一个专注数据。
二、快速入门
1.开发步骤
- 添加Mybatis依赖
- 创建User数据表
- 编写User实体类
- 编写映射配置文件UserMapper.xml
- 编写核心配置文件sqlMapConfig.xml
- 编写测试类
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核心配置文件分析
1.Mybatis常用标签
1.1 environments标签
数据库环境配置,支持多环境配置
transactionManager类型有两种
- JDBC:这个配置就是直接使用了JDBC的提交和回滚,它依赖于从数据源得到的连接来管理事务作用域。
- MANAGER:不会提交和回滚一个连接,而是让容器来管理实务的整个生命周期。
dataSource数据源*类型有三种
- UNPOOLED:每次请求获取新的连接结束后关闭连接。
- POOLED:表示使用连接池
- 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接口需要遵循以下规范
- Mapper.xml文件中的namespace与mapper接口的全限定名相同。
- Mapper接口方法名与Mapper.xml中定义的每个SQL的parameterType类型相同。
- Mapper接口方法的输入参数类型和mapper.xml中定义的每个parameterType的类型相同。
- 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也提供了对缓存的支持,分为一级缓存和二级缓存。
- 一级缓存是sqlSession级别的缓存。在操作数据库时需要构造sqlSession对象,在对象中有一个数据结构(HashMap)用于存储缓存数据。不同sqlSession之间的缓存数据区域HashMap是互不影响的。
- 二级缓存是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)]
通过日志信息可知,在发生增删操作之后,再次发生相同查询会访问数据库
总结
- 第一次发起查询用户id为1的用户信息,先去找缓存中是否有id为1的用户信息,如果没有,从数据库查询用户信息,将用户信息存储到一级缓存中。
- 如果中建sqlSession执行了增删改操作,则会清空sqlSession中的一级缓存,这样做的目的是为了让缓存中存储的是最新的信息,避免脏读。
- 第二次发起查询用户id为1的用户信息,先去找缓存中是否有id为1的用户信息,缓存中有直接从缓存中获取用户信息。
2.一级缓存源码分析
问题:
一级缓存是什么?
一级缓存什么时候创建、一级缓存的工作流程是怎样的?
分析
- 首先看代码,sqlSession为创建的执行sql的对象,因此从这作为入口找到clearCache()与缓存相关。
- sqlSession是接口找到其实现类DefaultSqlSession。
- DefaultSqlSession中clearCache执行的是Executor.clearLocalCache()。
- 找到Executor的实现类BaseExecutor。
- 看到其执行的第一句话就是PerpetualCache.clear()。
- PerpetualCache的clear方法中执行的是this.cache.clear()。看其属性this.cache就是一个HashMap。cache.clear()就是map.clear()
- 由以上分析可知,Mybatis一级缓存本质就是一个HashMap实现的。
- Mybatis到底是如何创建使用的一级缓存呢,我们想到Mybatis所有的查询都是通过Executor执行的找到他,发现其中还有一个缓存相关接口createCacheKey。
- 找到其实现类,其执行的方法就是创建了一个可以唯一确定查询的key,那么什么时候执行的呢,由之前的自定义Mybatis框架我们想到query方法。
- 具体看下图
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包中
具体实现步骤
- pom文件
<dependency>
<groupId>org.mybatis.caches</groupId>
<artifactId>mybatis-redis</artifactId>
<version>1.0.0-beta2</version>
</dependency>
- 配置文件
Mapper.xml
<cache type="org.mybatis.caches.redis.RedisCache" />
注解
@CacheNamespace(implementation = RedisCache.class)
public interface UserMapper {
- redis.properties
redis.host=localhost
redis.port=6379
redis.connectionTimeout=5000
redis.password=
redis.database=0
- 测试
直接执行之前的二级缓存测试方法,日志效果是相同的(不要忘了打开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源码分析
- RedisCache和普遍实现Mybatis缓存方案大同小异,无非是实现Cache接口并使用jedis操作缓存
- RedisCache在mybatis启动的时候,由MyBatis的CacheBuilder创建,创建的方式很简单,就是调用 RedisCache的带有String参数的构造方法,即RedisCache(String id);而在RedisCache的构造方法中, 调用了 RedisConfigu rationBuilder(读取配置文件信息)来创建 RedisConfig 对象,并使用 RedisConfig 来创建JedisPool(Jedis池)。
- 另外两个重要的方法就是putObject和getObject,可以知道其就是使用的Redis的Hash来存储的数据。
八、Mybatis插件
Mybatis轻松入门(仅要求会用看着一个就够了,略过源码分析部分即可)的更多相关文章
- 入门数据结构与算法,看这一个就够了,知识点+LeetCode实战演练
本笔记来自拉钩教育300分钟搞定算法面试 算法与数据结构 要掌握一种数据结构,就必须要懂得分析它的优点和缺点. 在考虑是否应当采用一种数据结构去辅助你的算法时,请务必考虑它的优缺点,看看它的缺点是否会 ...
- 通过源码分析MyBatis的缓存
前方高能! 本文内容有点多,通过实际测试例子+源码分析的方式解剖MyBatis缓存的概念,对这方面有兴趣的小伙伴请继续看下去~ MyBatis缓存介绍 首先看一段wiki上关于MyBatis缓存的介绍 ...
- 【Netty之旅四】你一定看得懂的Netty客户端启动源码分析!
前言 前面小飞已经讲解了NIO和Netty服务端启动,这一讲是Client的启动过程. 源码系列的文章依旧还是遵循大白话+画图的风格来讲解,本文Netty源码及以后的文章版本都基于:4.1.22.Fi ...
- [源码分析] 从源码入手看 Flink Watermark 之传播过程
[源码分析] 从源码入手看 Flink Watermark 之传播过程 0x00 摘要 本文将通过源码分析,带领大家熟悉Flink Watermark 之传播过程,顺便也可以对Flink整体逻辑有一个 ...
- [源码分析] 从实例和源码入手看 Flink 之广播 Broadcast
[源码分析] 从实例和源码入手看 Flink 之广播 Broadcast 0x00 摘要 本文将通过源码分析和实例讲解,带领大家熟悉Flink的广播变量机制. 0x01 业务需求 1. 场景需求 对黑 ...
- mybatis源码分析:启动过程
mybatis在开发中作为一个ORM框架使用的比较多,所谓ORM指的是Object Relation Mapping,直译过来就是对象关系映射,这个映射指的是java中的对象和数据库中的记录的映射,也 ...
- C++ STL编程轻松入门基础
C++ STL编程轻松入门基础 1 初识STL:解答一些疑问 1.1 一个最关心的问题:什么是STL 1.2 追根溯源:STL的历史 1.3 千丝万缕的联系 1.4 STL的不同实现版本 2 牛刀小试 ...
- JavaScript面向对象轻松入门之封装(demo by ES5、ES6、TypeScript)
本章默认大家已经看过作者的前一篇文章 <JavaScript面向对象轻松入门之抽象> 为什么要封装? 封装(Encapsulation)就是把对象的内部属性和方法隐藏起来,外部代码访问该对 ...
- Java-MyBatis:MyBatis 3 入门
ylbtech-Java-MyBatis:MyBatis 3 入门 1.返回顶部 1. 入门 安装 要使用 MyBatis, 只需将 mybatis-x.x.x.jar 文件置于 classpath ...
随机推荐
- C语言:带参数的宏与函数的区别
带参数的宏和函数很相似,但有本质上的区别:宏展开仅仅是字符串的替换,不会对表达式进行计算:宏在编译之前就被处理掉了,它没有机会参与编译,也不会占用内存.而函数是一段可以重复使用的代码,会被编译,会给它 ...
- Day5 Scanner对象学习.
Scanner对象 Java.until.Scanner 我们可以通过Scanner类来获取用户的输入. 基本语法: Scanner s = new Scanner (System . in) ; 通 ...
- Ubuntu Server连接Wi-Fi
本文将介绍Ubuntu Server如何通过命令行使用wpa_supplicant连接Wi-Fi 环境 Ubuntu Server 20.04(64位) wpasupplicant 配置 1. 安装 ...
- 深入刨析tomcat 之---第3篇 HTTP/1.1 长连接的实现原理
writedby 张艳涛 长连接是HTTP/1.1的特征之一,1.1出现的原因是因为一个客户请求一个网页,这是一个http请求,这个网页中如果有图片,那么也会变为一个http请求,对于java客户端, ...
- [源码解析] 机器学习参数服务器 Paracel (1)-----总体架构
[源码解析] 机器学习参数服务器 Paracel (1)-----总体架构 目录 [源码解析] 机器学习参数服务器 Paracel (1)-----总体架构 0x00 摘要 0x01使用 1.1 配置 ...
- C# WinForm 数据库连接及对数据库的相关操作
1.首先在App.config配置文件中配置数据库连接字符串: <appSettings> <add key="connectionstring" value=& ...
- 冲击BATZ!GitHub近8.3K+的Android进阶指南,面试再也不愁了
过去十年是移动互联网蓬勃发展的黄金期,相信每个人也都享受到了移动互联网红利,在此期间,移动互联网经历了曙光期.成长期.成熟期.现在来说已经进入饱和期. 依然记得在 2010-2013 年期间,从事移动 ...
- GitHub标星8k,字节跳动高工熬夜半月整理的“组件化实战学习手册”,全是精髓!
前言 什么是组件化? 最初的目的是代码重用,功能相对单一或者独立.在整个系统的代码层次上位于最底层,被其他代码所依赖,所以说组件化是纵向分层. 为什么要使用组件化? 当我们的项目越做越大的时候,有时间 ...
- srt文件的时间轴平移处理
有时srt字幕文件与视频文件的时间不完全吻合,有一个时间差,这就需要对srt文件的时间轴进行平移,具备这个功能的软件很多,比如:Subtitle Tool, subresync, sabbu, Sub ...
- Linux 内核预备知识:浅析 offsetof 宏以及新手的所思所想
最近一头扎进了 Linux 内核的学习中,对于我这样一个没什么 C 语言基础的新生代 Java 农民工来说实在太痛苦了.Linux 内核的学习,需要的基础知识太多太多了:C 语言.汇编语言.数据结构与 ...