模拟MyBatis源码- V1.0

模拟myBatis源码的类结构
这里写图片描述

自己手动实现MyBatis源码:
第一步, 生命一个SqlSession, SqlSession两大主要组件, Configuration, Executor.,
其中Configuraion保存了所有配置信息如: Mapper,DataSource, Trancation等,
这次 v1.0版只编写最简单的Mapper信息

模拟SqlSession代码:

public class AutoSqlSession {

    private AutoConfiguration configuration;
    private AutoExecutor executor;

    public AutoSqlSession(AutoConfiguration configuration, AutoExecutor executor) {
        this.configuration = configuration;
        this.executor = executor;
    }
    //返回Mapper
    public <T> T GetMapper(Class clazz) {
        return (T) this.configuration.getMapper(clazz,this);
    }
//直接查询
    public <T> T SelectOne(String stateMent) {
        return this.executor.query(stateMent);
    }    
}

AutoConfiguration:
包含XMLParser静态类, 用来模拟保存Configuraion中的Mapper信息,
包含getMapper, 用来返回用户IMapper的代理.
代码:

public class AutoConfiguration {

//用来返回代理后的用户Mapper接口
    public <T> T getMapper(Class<T> clazz, AutoSqlSession session) {
        AutoMapperProxy proxy = new AutoMapperProxy(session);
        return (T) Proxy.newProxyInstance(this.getClass().getClassLoader(), new Class[]{clazz}, proxy);
    }

//模拟存储Mapper.xml中的用户SQL配置信息
   public static class XMLParser {
        static Map mapSqls = new HashMap<>();

        static {
            mapSqls.put("com.gupaoedu.mybatis.Auto.TestMapper.selectByPrimaryKey", "select *from User where id=?");
        }

        static String GetStatemenet(String strKey) {
            return String.valueOf(mapSqls.get(strKey));
        }
    }
}

SqlSession中所有于数据库的交互全部由Executor类执行, 模拟创建Executor执行器类

// 定义接口IExecutor 
public interface IExecutor {
    <T> T query(String strStateMent);
}


//定义IExecutor 的实现类
public class AutoExecutor implements IExecutor {

    @Override
    //此处使用最原始的JDBC连接数据库
    public <T> T query(String strStateMent) {
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        UserBean test = null;
        try {
            Class.forName("com.mysql.jdbc.Driver");
            connection = DriverManager.getConnection("jdbc:mysql://x.x.x.x:3306/test?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC", "x", "x");

            preparedStatement = connection.prepareStatement(strStateMent);
            ResultSet rs = preparedStatement.executeQuery();
            while (rs.next()) {
                test = new UserBean();
                test.setId(rs.getInt(1));
                test.setName(rs.getString(2));
                test.setAge(rs.getInt(3));
                test.setSex(rs.getBoolean(4));
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            try {
                if (null != connection) {
                    connection.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        return (T)test;
    }
}

SqlSession使用getMapper返回用户接口的代理,代理类如下:

public class AutoMapperProxy implements InvocationHandler {
    private AutoSqlSession session;

    public AutoMapperProxy(AutoSqlSession session) {
        this.session = session;
    }


//注意用户接口的调用在此处被代理为sqlSession.SelectOne方法,
//SelelectOne方法最终由 Executor.query去执行.
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        if ((method.getDeclaringClass().getName() + "." + method.getName()).equals("com.gupaoedu.mybatis.Auto.TestMapper.selectByPrimaryKey")) {
            String strSql = AutoConfiguration.XMLParser.GetStatemenet("com.gupaoedu.mybatis.Auto.TestMapper.selectByPrimaryKey");
            strSql= strSql.replace("?", args[0].toString());
            return session.SelectOne(strSql);
        } else {
            return method.invoke(this, args);
        }
    }
}

模拟用户调用:
创建Bean:

public class UserBean {

    private int id;
    private String name;
    private int age;
    private boolean sex;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public boolean isSex() {
        return sex;
    }

    public void setSex(boolean sex) {
        this.sex = sex;
    }
}

创建用户Mapper接口

public interface TestMapper {
    UserBean selectByPrimaryKey(Integer userId);
}

测试代码:

public class AutoBatisTest {
    public static void main(String[] args) {
        AutoSqlSession session  =new AutoSqlSession(new AutoConfiguration(),new AutoExecutor());

        TestMapper mapper = session.GetMapper(TestMapper.class);

        //此处注意:用户接口mapper 没有实现类,接口方法调用被悄悄代理为用MapperProxy实例去请求数据库.
        UserBean bean = mapper.selectByPrimaryKey(1);
        System.out.println(bean.getName());
    }
}

项目源码路径:
https://gitee.com/yangxulong/autoMyBaits

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值