手写了一个ORM框架

simple-ibatis 手写了一个ORM框架

前文介绍

在学习mybatis源码之余,自己完成了一个简单的ORM框架,已完成基本SQL的执行和对象关系映射。本周在此基础上,又加入了缓存和事务功能。
源码地址
前叙博文地址

缓存 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{

    private static Map<String,Object> map = new HashMap<>();

    @Override
    public void putCache(String key, Object val) {
        map.put(key,val);
    }

    @Override
    public Object getCache(String key) {
        return map.get(key);
    }

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

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

    @Override
    public void removeCache(String key) {
        map.remove(key);
    }
}

内部使用HashMap来实现一个简单的缓存器,基本是对HashMap的封装。

具备LRU淘汰策略-LruCache

/**
 * @author xiabing
 * @description: 缓存包装类
 */
public class LruCache implements Cache{

    private static Integer cacheSize = 100;

    private static Float loadFactory = 0.75F;

    private Cache trueCache;

    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
            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.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源码。mybatis缓存实现

项目代码展示

可参考github项目中Test类中shouldGetCache()方法

 @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)

项目代码展示

@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();
    }

上述代码在github项目中Test类中shouldOpenTransaction()方法上,可自行debug测试。

结束语

此次在已有的基础上增加了缓存和事务的功能。又是一次学习之旅。因为代码全手写,没有COPY任何一句代码,不是很完善,请见谅。如果觉的感兴趣,请给我个star支持下。因为自己想一直去维护这个项目,如果你也感兴趣,可以私聊我和我一起做下去,一起写好这个开源项目。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值