天天看点

架构基础学习一 手写持久层框架及mybatis源码分析(2)

作者:上校马孔多在下雨

1.5 ⾃定义框架优化

通过上述我们的⾃定义框架,我们解决了JDBC操作数据库带来的⼀些问题:例如频繁创建释放数据库连接,硬编码,⼿动封装返回结果集等问题,但是现在我们继续来分析刚刚完成的⾃定义框架代码,有没有什么问题?

问题如下:

1、dao的实现类中存在重复的代码,整个操作的过程模板重复(创建sqlsession,调⽤sqlsession⽅法,关闭 sqlsession)

2、dao的实现类中存在硬编码,调⽤sqlsession的⽅法时,参数statement的id硬编码

解决:使⽤代理模式来创建接⼝的代理对象

package com.tyf.test;

import com.tyf.mapper.IUserDao;
import com.tyf.mybatis.Resources;
import com.tyf.mybatis.SqlSession;
import com.tyf.mybatis.SqlSessionFactory;
import com.tyf.mybatis.SqlSessionFactoryBuilder;
import com.tyf.pojo.User;
import org.junit.Test;

import java.io.InputStream;
import java.util.List;


public class IPersistenceTest {

    @Test
    public void test() throws Exception {
        // 此处经常出现读取不到文件的问题,时好时坏。最终解决
        // InputStream resourceAsSteam = this.getClass().getClassLoader().getResourceAsStream("classpath:SqlMapConfig.xml");
        InputStream resourceAsSteam =  Resources.class.getResourceAsStream("/SqlMapConfig.xml");

        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsSteam);
        SqlSession sqlSession = sqlSessionFactory.openSession();

        //调用
        /*User user = new User();
        user.setId(1);
        user.setUsername("tyf");
        User user2 = sqlSession.selectOne("user.selectOne", user);

        System.out.println(user2);*/

       /* List<User> users = sqlSession.selectList("user.selectList");
        for (User user1 : users) {
            System.out.println(user1);
        }*/

        IUserDao userDao = sqlSession.getMapper(IUserDao.class);

        List<User> all = userDao.findAll();
        for (User user1 : all) {
            System.out.println(user1);
        }
    }
}
           

在sqlSession中添加⽅法及实现类中方法实现

public <T> T getMapper(Class<T> mapperClass) throws Exception;           
@Override
public <T> T getMapper(Class<T> mapperClass) throws Exception {
    T o = (T) Proxy.newProxyInstance(mapperClass.getClassLoader(), new Class[]{mapperClass}, new InvocationHandler() {
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            String methodName = method.getName();
            String className = method.getDeclaringClass().getName();
            String statementId = className + "." + methodName;
            MappedStatement mappedStatement = configuration.getMappedStatementMap().get(statementId);
            Type returnType = method.getGenericReturnType();
            //List list = new ArrayList();
            // 判断是否实现泛型类型参数化
            if (returnType instanceof ParameterizedType) {
                return selectList(statementId, args);
            }
            return selectOne(statementId, args);
        }
    });
    return o;
}           

继续阅读