public static void main(String[] args) throws IOException {
System.out.println("测试javaEE使用mybatis-plus");
InputStream is = Resources.getResourceAsStream("conf/mybatis_conf.xml");
// GenericTypeUtils.setGenericTypeResolver(null); // 3.5 javaEE 需要手动添加
// SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
SqlSessionFactory factory = new MybatisSqlSessionFactoryBuilder().build(is);
// SqlSession session = factory.openSession();
// UserMapper userMapper = session.getMapper(UserMapper.class);
// System.out.println("--------session start---------");
// System.out.println(userMapper.selectById(1));
// System.out.println("--------session end---------");
// SqlSession session2 = factory.openSession();
// System.out.println("--------session2 start---------");
// UserMapper userMapper1 = session2.getMapper(UserMapper.class);
// System.out.println("--------session2 end---------");
// User user1 = null;
// System.out.println("--------session start---------");
// System.out.println(user1 = userMapper1.selectById(1));
// System.out.println("--------session end---------");
//
// // 测试一级缓存
// System.out.println("------------------------------");
// user1.setEmail(System.currentTimeMillis() + "");
// System.out.println("--------session2 start update---------");
// userMapper1.updateById(user1);
// session2.commit();
// System.out.println("--------session2 end update---------");
// System.out.println("--------session start---------");
// System.out.println(userMapper.selectById(1)); // 会话1依然是老数据
// System.out.println("--------session end---------");
// System.out.println("--------session2 start---------");
// System.out.println(userMapper1.selectById(1)); // 会话2为最新数据
// System.out.println("--------session2 end---------");
// // 测试一级缓存,是否有一个更新会导致 当前会话中的所有缓存给清空
// System.out.println("测试一级缓存,是否有一个更新会导致 当前会话中的所有缓存给清空");
// User user2 = new User();
// user2.setEmail(System.currentTimeMillis() + "");
// System.out.println("--------session start update---------");
// userMapper.updateById(user2);
// session.commit();
// System.out.println("--------session end update---------");
// System.out.println("--------session start---------");
// System.out.println(userMapper.selectById(1)); // 会话1存在更新缓存,数据最新获取
// System.out.println("--------session end---------");
// // 二级缓存
二级缓存测试(factory);
}
private static void 二级缓存测试(SqlSessionFactory factory) {
System.out.println("mybatis 二级缓存测试");
SqlSession session3 = factory.openSession();
UserMapper mapper3 = session3.getMapper(UserMapper.class);
// 同一个Mapper下的namespace update 会清空该namespace下的 CachingExecutor的tcm所有 缓存
// 不同的namespace 不相互影响
// User user9 = new User();
// user9.setAge(100);
// user9.setEmail("*****@163.com");
// user9.setName("lilei");
// System.out.println("--------session3 start insert---------");
// mapper3.insert(user9);
// session3.commit();
// System.out.println("--------session3 end insert---------");
System.out.println("--------session3 start---------");
System.out.println(mapper3.getAllUsers());
session3.commit(); // 当前session 二级缓存持久化
System.out.println("--------session3 end---------");
// 不同的session测试二级缓存
SqlSession session4 = factory.openSession();
UserMapper mapper4 = session4.getMapper(UserMapper.class);
System.out.println("--------session4 start---------");
System.out.println(mapper4.getAllUsers());
System.out.println("--------session4 end---------");
System.out.println("--------session3 start---------");
mapper3 = session3.getMapper(UserMapper.class);
System.out.println(mapper3.getAllUsers());
System.out.println("--------session3 end---------");
}
一、Mapper的初始化
jdk动态代理Mapper
二、mybatis数据库连接池
三、mybatis缓存
一二级缓存key皆是CacheKey。
CacheExecutor为Executor的装饰器类,mybatis开启了二级换粗之后,即可有次装饰器。
优先二级缓存(全局的,所有会话session共享的)
其次一级缓存(基于session会话的)
二级缓存调用堆栈
tcm.put只是压入TrasactionCache的entriesToAddCommit的Map。现在是session对话私有的,还未压入目标Cache。待后续session.commit或者close()
tcm->同步块Cache(线程安全)->日志统计Cache(总请求数、缓存命中率)->序列化Cache->策略Cache(LRU、FIFO、SOFT、WEAK)->目标Cache(map操作)
当session.close()之后,或者session.commit之后二级缓存才会提交,写入Map。
否则同一个session下,二级缓存是不会命中的,只能走后续的一级缓存。
二级缓存全局共享是基于Configuration:
基于Mapper的namespace + sql接口进行Map存储Mapstatement。
四、redis作为mybatis二级缓存介质
public class JedisPoolConf {
public static JedisPool pool = null;
public static JedisPool getPool() {
if (pool == null) {
JedisPoolConfig config = new JedisPoolConfig();
config.setMaxIdle(10);
config.setMaxTotal(100);
config.setMaxWait(Duration.ofSeconds(30));
pool = new JedisPool(config, "localhost", 6379, 30,"123456", 10);
}
return pool;
}
}
public class RedisCache implements Cache {
private JedisPool jedisPool = JedisPoolConf.getPool();
private final String id;
public RedisCache(String id) {
this.id = id;
}
@Override
public String getId() {
return id;
}
@Override
public void putObject(Object key, Object value) {
Jedis jedis = jedisPool.getResource();
try {
jedis.hset(id.getBytes(), key.toString().getBytes(), serialize(value));
} catch (Exception e) {
e.printStackTrace();
System.out.println(e.getMessage());
} finally {
jedis.close();
}
}
@Override
public Object getObject(Object key) {
Jedis jedis = jedisPool.getResource();
Object back = null;
try {
byte[] v = jedis.hget(id.getBytes(), key.toString().getBytes());
if (v != null) {
back = deserialize(v);
}
} catch (Exception e) {
e.printStackTrace();
System.out.println(e.getMessage());
} finally {
jedis.close();
}
return back;
}
@Override
public Object removeObject(Object key) {
Jedis jedis = jedisPool.getResource();
try {
return jedis.hdel(id.getBytes(), key.toString().getBytes());
} catch (Exception e) {
e.printStackTrace();
System.out.println(e.getMessage());
} finally {
jedis.close();
}
return 0;
}
@Override
public void clear() {
Jedis jedis = jedisPool.getResource();
try {
jedis.del(id.getBytes());
} catch (Exception e) {
e.printStackTrace();
System.out.println(e.getMessage());
} finally {
jedis.close();
}
}
@Override
public int getSize() {
return 0;
}
@Override
public ReadWriteLock getReadWriteLock() {
return null;
}
private byte[] serialize(Object value) {
try (ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos)) {
oos.writeObject(value);
oos.flush();
return bos.toByteArray();
} catch (Exception e) {
throw new CacheException("Error serializing object. Cause: " + e, e);
}
}
private Serializable deserialize(byte[] value) {
SerialFilterChecker.check();
Serializable result;
try (ByteArrayInputStream bis = new ByteArrayInputStream(value);
ObjectInputStream ois = new SerializedCache.CustomObjectInputStream(bis)) {
result = (Serializable) ois.readObject();
} catch (Exception e) {
throw new CacheException("Error deserializing object. Cause: " + e, e);
}
return result;
}
}
调用堆栈