手写mybatis框架-增加缓存&事务功能

缓存 com.simple.ibatis.cache
缓存接口-Cache
复制代码
public interface Cache {

/**放入缓存*/
void putCache(String key,Object val);

/**获取缓存*/
Object getCache(String key);

/**清空缓存*/
void cleanCache();

/**获取缓存健数量*/
int getSize();

/**移除key的缓存*/
void removeCache(String key);

}
复制代码
自定义框架缓存接口,提供基本的增删改查功能。

缓存基本实现类-SimpleCache
复制代码
public class SimpleCache implements Cache{
// 内部使用HashMap作为缓存实现
private static Map<String,Object> map = new HashMap<>();
// 调用map.put()方法实现存缓存功能
@Override
public void putCache(String key, Object val) {
map.put(key,val);
}
// 调用map.get()方法实现取缓存功能
@Override
public Object getCache(String key) {
return map.get(key);
}
// 调用map.clear()方法实现清空缓存功能
@Override
public void cleanCache() {
map.clear();
}
// 调用map.size()方法获取缓存数量
@Override
public int getSize() {
return map.size();
}
// 调用map.remove()方法移除缓存
@Override
public void removeCache(String key) {
map.remove(key);
}
}
复制代码
simple-ibatis完成对HasaMap的封装,实现了基本的缓存获取,删除,清除等功能。

具备LRU淘汰策略-LruCache
复制代码
/**

  • @author xiabing

  • @description: 缓存包装类,具备Lru淘汰策略功能
    */
    public class LruCache implements Cache{
    // 默认缓存数
    private static Integer cacheSize = 100;
    // 负载因子
    private static Float loadFactory = 0.75F;
    // 真实缓存
    private Cache trueCache;
    // 重写LinkedHashMap方法实现Lru功能
    private Map<String,Object> linkedCache;
    // 待移除的缓存元素
    private static Map.Entry removeEntry;

    public LruCache(Cache trueCache){
    this(cacheSize,loadFactory,trueCache);
    }

    public LruCache(Integer cacheSize, Float loadFactory, Cache trueCache) {
    this.cacheSize = cacheSize;
    this.loadFactory = loadFactory;
    this.trueCache = trueCache;
    this.linkedCache = new LinkedHashMap<String, Object>(cacheSize,loadFactory,true){
    @Override
    // 当缓存数大于设置的默认缓存数时,linkedHashMap会淘汰最近最少使用的元素,获取此元素,在真实缓存中淘汰即可
    protected boolean removeEldestEntry(Map.Entry eldest) {
    if(getSize() > cacheSize){
    removeEntry = eldest;
    return true;
    }
    return false;
    }
    };
    }

    @Override
    public void putCache(String key, Object val) {
    this.trueCache.putCache(key,val);
    this.linkedCache.put(key,val);
    if(removeEntry != null){
    // 若找到了最近最少元素,则进行移除
    removeCache((String)removeEntry.getKey());
    removeEntry = null;
    }
    }

    @Override
    public Object getCache(String key) {
    // linkedCache获取的意义是触发linkedHashMap元素排序
    linkedCache.get(key);
    return trueCache.getCache(key);
    }

    @Override
    public void cleanCache() {
    trueCache.cleanCache();
    linkedCache.clear();
    }

    @Override
    public int getSize() {
    return trueCache.getSize();
    }

    @Override
    public void removeCache(String key) {
    trueCache.removeCache(key);
    }
    }
    复制代码
    LruCache是根据LinkedHashMap的特性来实现,若对此有疑问,可参考mybatis关于LruCache功能的实现 - mybatis缓存介绍

项目代码测试
复制代码
@Test
// 测试缓存获取
public void shouldGetCache() throws SQLException {
// 初始化连接池
PoolDataSource poolDataSource = new PoolDataSource(“com.mysql.jdbc.Driver”,“jdbc:mysql://101.132.150.75:3306/our-auth”,“root”,“root”);
Config config = new Config(“com/simple/ibatis/mapper”,poolDataSource);
// 设置全局配置,开启缓存
config.setOpenCache(true);
// 获取执行器
Executor simpleExecutor = config.getExecutor();
UserMapper userMapper = simpleExecutor.getMapper(UserMapper.class);

    User user = new User();
    user.setId(1);
    user.setName("root");
   // 第一次调用
    List<User> userList = userMapper.getUsers(user);
    // 第二次调用,我在源码中有打印输出,若使用了缓存,则打印语句
    List<User> userList1 = userMapper.getUsers(user);
    
    simpleExecutor.close();
}

复制代码
结果打印如下 this is cache .感兴趣的可以自己试下

cache我设置了全局可配置,默认生成的是LruCache。并在更新,修改,删除的SQL操作前强制刷新缓存。详细代码逻辑见项目中SimpleExecutor类。

事务功能com.simple.ibatis.transaction
事务接口-Transaction
复制代码
/**

  • @Author xiabing
  • @Desc 增加事务功能
    **/
    public interface Transaction {
    /*获取链接/
    Connection getConnection() throws SQLException;
    /*提交/
    void commit() throws SQLException;
    /*回滚/
    void rollback() throws SQLException;
    /*关闭/
    void close() throws SQLException;
    }
    复制代码
    JDBC事务-SimpleTransaction
    复制代码
    package com.simple.ibatis.transaction;

import com.simple.ibatis.datasource.PoolDataSource;

import java.sql.Connection;
import java.sql.SQLException;

/**

  • @Author xiabing

  • @Desc 事务的简单实现
    **/
    public class SimpleTransaction implements Transaction{

    private Connection connection; // 数据库连接
    private PoolDataSource dataSource; // 数据源
    private Integer level = Connection.TRANSACTION_REPEATABLE_READ;; // 事务隔离级别
    private Boolean autoCommmit = true; // 是否自动提交

    public SimpleTransaction(PoolDataSource dataSource){
    this(dataSource,null,null);
    }

    public SimpleTransaction(PoolDataSource dataSource, Integer level, Boolean autoCommmit) {
    this.dataSource = dataSource;
    if(level != null){
    this.level = level;
    }
    if(autoCommmit != null){
    this.autoCommmit = autoCommmit;
    }
    }

    @Override
    public Connection getConnection() throws SQLException{
    this.connection = dataSource.getConnection();

     this.connection.setAutoCommit(autoCommmit);
    
     this.connection.setTransactionIsolation(level);
    
     return this.connection;
    

    }

    @Override
    public void commit() throws SQLException{
    if(this.connection != null){
    this.connection.commit();
    }
    }

    @Override
    public void rollback() throws SQLException{
    if(this.connection != null){
    this.connection.rollback();
    }
    }

    /*关闭链接前,若设置了自动提交为false,则必须进行回滚操作/
    @Override
    public void close() throws SQLException{
    if(!autoCommmit && connection != null){
    connection.rollback();
    }
    /*放回连接池/
    if(connection != null){
    dataSource.removeConnection(connection);
    }
    /*链接设为null/
    this.connection = null;
    }
    }
    复制代码
    simpleTransaction主要将事务管理功能交给了数据库本身(即connection),事务隔离级别默然是mysql的事务隔离级别。通过对Connection的管理,进而实现对connection一系列操作的事务控制。

复制代码
Test
public void shouldOpenTransaction() {
/*基本配置/
PoolDataSource poolDataSource = new PoolDataSource(“com.mysql.jdbc.Driver”,“jdbc:mysql://101.132.150.75:3306/our-auth”,“root”,“root”);
Config config = new Config(“com/simple/ibatis/mapper”,poolDataSource);
/*设置为启用事务,关闭自动提交/
config.setOpenTransaction(true);

    /**获取执行器*/
    Executor simpleExecutor = config.getExecutor();
    UserMapper userMapper = simpleExecutor.getMapper(UserMapper.class);

    User user = new User();
    user.setId(1);
    user.setName("xiabing");
    /**更新名字为xiabing,但未提交*/
    userMapper.update(user);

    User user1 = userMapper.getUserById(1);
    /**获取ID为1的名字,为root,说明上文的语句还没有提交*/
    System.out.println(user1.getName());
    /**事务提交语句*/
    //simpleExecutor.commit();
}
龙华大道1号http://www.kinghill.cn/LongHuaDaDao1Hao/index.html

猜你喜欢

转载自blog.csdn.net/weixin_45032957/article/details/108600052