-
mybatis简单介绍
- mybatis介绍
MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 POJOs(Plain Ordinary Java Object,普通的 Java对象)映射成数据库中的记录--百度百科
- 代码执行流程
// 1、定义mybatis_config.xml文件 String resorce = "mybatis_config.xml"; // 2、加载配置文件 Reader reader = Resources.getResourceAsReader(resorce); // 3、获取SqlSessionFactory SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader); // 4、创建 SqlSession SqlSession sqlSession = sqlSessionFactory.openSession(); // 5.执行sql语句 UserEntity userEntity = sqlSession.selectOne("com.pitch.mapper.UserMapper.getUser", 1);
- SqlSession介绍
SqlSession提供select/insert/update/delete方法
每个线程都应该有它自己的 SqlSession 实例。SqlSession 的实例不是线程安全的,因此是不能被共享的。 - Mybatis之Mapper接口绑定原理(代理设计模式--动态代理)
原理参考: https://www.cnblogs.com/demingblog/p/9544774.html
-
mybatis一级缓存
- 原理
mybatis默认开启一级缓存
mybatis的一级缓存是SqlSession级别的缓存,在操作数据库的时候需要先创建SqlSession会话对象,在对象中有一个HashMap用于存储缓存数据,此HashMap是当前会话对象私有的,别的SqlSession会话对象无法访问
- 步骤流程
1.第一次执行select时,会将查询到的数据写入SqlSession内的HashMap中缓存起来。使用[namespace:sql:参数]作为
HashMap的key
2.第二次执行select时,如果查询的参数sql一样,就直接从缓存中返回数据,从而提高了效率
3.如果SqlSession执行了DML操作(insert、update、delete),并commit了,那么mybatis就会清空当前SqlSession缓存中
的所有缓存数据,这样可以保证缓存中的存的数据永远和数据库中一致,避免出现脏读
- 缺点
因为一级缓存是存放在服务器内存中,如何服务器集群的时候,每个服务器JVM的sqlSession有自己独立的缓存相互之间不存在共享,所以在服务器集群的时候容易产生数据冲突问题。
- 解决方案
1. 在每条select语句生成随机参数,是每次查询的语句都不一样。--不推荐,map集合内存会溢出
2.使用sqlSession.update(); 方法清除缓存
3. 开启二级缓存
- mybatis二级缓存
- 原理
mybatis在查询的时候先走的是二级缓存,如果二级缓存没有的话,就去一级缓存中查询......
二级缓存默认是关闭的(默认是true,但是因为默认没有配置二级缓存的存储介质),需要配置 - 如何开启二级缓存
// 1、在mybatis-config.xml开启缓存,默认true <setting name="cacheEnabled" value="true"/> // 2、在UserMapper.xml中配置缓存 <cache type="com.pitch.cache.RedisCache" /> // 3、创建 RedisCache.java类,必须实现org.apache.ibatis.cache.Cache接口 使用配置的RedisTemplate类来实现Cache接口中的方法.........
- 二级缓存回收策略
LRU:最近最少使用的策略,移除最长时间不被使用的对象。
FIFO:先进先出策略,按对象进入缓存的顺序来移除它们。
SOFT:软引用策略,移除基于垃圾回收器状态和软引用规则的对象。
WEAK:弱引用策略,更积极地移除基于垃圾收集器状态和弱引用规则的对象。
- 一级缓存与二级缓存区别
- 一级缓存是SqlSession级别的缓存。是存放JVM中,不能共享
- 二级缓存是mapper级别的缓存,是存放redis等其他数据库中。二级缓存是跨SqlSession的,可以共享,
- Springboot开启二级缓存
- 创建MybatisRedisCache.java,实现Cache接口
import org.apache.ibatis.cache.Cache; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; public class MybatisRedisCache implements Cache { private static Logger logger = LoggerFactory.getLogger(MybatisRedisCache.class); private Jedis redisClient = createReids(); private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock(); private String id; public MybatisRedisCache(final String id) { if (id == null) { throw new IllegalArgumentException("Cache instances require an ID"); } this.id = id; } public String getId() { return this.id; } public int getSize() { return Integer.valueOf(redisClient.dbSize().toString()); } public void putObject(Object key, Object value) { redisClient.set(SerializeUtil.serialize(key.toString()), SerializeUtil.serialize(value)); } public Object getObject(Object key) { return SerializeUtil.unserialize(redisClient.get(SerializeUtil.serialize(key.toString()))); } public Object removeObject(Object key) { return redisClient.expire(SerializeUtil.serialize(key.toString()), 0); } public void clear() { redisClient.flushDB(); } public ReadWriteLock getReadWriteLock() { return readWriteLock; } protected static Jedis createReids() { JedisPool pool = new JedisPool("127.0.0.1", 6379); return pool.getResource(); } }
- 缓存注解
import com.pitch.api.cache.MybatisRedisCache; import org.apache.ibatis.annotations.CacheNamespace; import org.apache.ibatis.annotations.Insert; import org.apache.ibatis.annotations.Select; import java.util.List; @CacheNamespace(implementation = MybatisRedisCache.class) public interface UserMapper { @Select("SELECT * FROM user_info;") public List<UserEntity> findByUser(); }
- 开启缓存
@EnableCaching
参考文档@SpringBootApplication @MapperScan("com.pitch.user.mapper") @EnableCaching public class UserApp { public static void main(String[] args) { SpringApplication.run(UserApp.class); } }
https://blog.csdn.net/weixin_37139197/article/details/82908377
https://blog.csdn.net/suifeng629/article/details/81586305