暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

mybatis框架分析之实现自己的framework(下)

Alleria Windrunner 2020-01-15
178
之前的两篇我们自己撸完了配置文件加载的代码,从这篇开始我们来撸一下sqlSession执行流程。还是先把使用mybatis的示例代码摆出来:

public class Test {


private SqlSessionFactory sqlSessionFactory;

@Override

public User findUserById(int id) throws Exception {

SqlSession session = sqlSessionFactory.openSession(); 

User user = null;

try {

//通过sqlsession调用selectOne方法获取一条结果集 

//参数1:指定定义的 statement的id

//参数2:指定向statement中传递的参数 

user = session.selectOne("test.findUserById", id); 

System.out.println(user);

} finally{ 

session.close();

}

return user; 

}

}



根据《mybatis框架分析之需要解决的问题》中我们的分析,我们抽象出一个SqlSession接口,接口中方法定义如下:
  1. Object selectOne(String statementId, Object param);

  2. List<Object> selectList(String statementId, Object param);


同时我们参照mybatis的实现,对于SqlSession我们提供一个默认的DefaultSqlSession并且提供一个工厂类SqlSessionFactory。另外对于DefaultSqlSession中的两个方法的jdbc操作我们并不自己实现,而是使用Executor接口去实现,针对Executor我们也提供一个默认的实现类SimpleExecutor。整体回顾梳理我们需要的接口和类:
  1. SqlSession

  2. DefaultSqlSession

  3. SqlSessionFactory

  4. DefaultSqlSessionFactory

  5. DefaultSqlSessionFactoryBuilder

  6. Executor

  7. SimpleExecutor


接下来的工作就是撸代码了,先从SqlSession接口开始:

package com.eleven.session;



import java.util.List;


/**

 * sql执行会话

 * @author eleven

 * @see

 * @since

 */


public interface SqlSession {


    **

     * 查询单条记录

     * @param statementId

     * @param param

     * @return

     */

    <T> T selectOne(String statementId, Object param);


    **

     * 查询集合记录

     * @param statementId

     * @param param

     * @return

     */

    <T> List<T> selectList(String statementId, Object param);

}

然后是DefaultSqlSession:

package com.eleven.session;


import com.eleven.config.Configuration;

import com.eleven.config.MappedStatement;


import java.util.List;


/**

 * sql执行会话默认实现类

 * @author eleven

 * @see

 * @since

 */


public class DefaultSqlSession implements SqlSession {


    private Configuration configuration;


    public DefaultSqlSession(Configuration configuration) {

        this.configuration = configuration;

    }


    @Override

    public <T> T selectOne(String statementId, Object param) {

        List<T> resultList = this.selectList(statementId, param);

        if (resultList != null && resultList.size() == 1) {

            return resultList.get(0);

        }

        return null;

    }


    @Override

    public <T> List<T> selectList(String statementId, Object param) {

        MappedStatement  mappedStatement  =                                                                            configuration.getMappedStatements().get(statementId);

        Executor executor = new SimpleExecutor();

        return executor.query(configuration, mappedStatement, param);

    }

}

这里selectOne()执行调用selectList()取第一个结果集。接下来是Executor和SimpleExecutor:

package com.eleven.session;


import com.eleven.config.Configuration;

import com.eleven.config.MappedStatement;


import java.util.List;


/**

 * Sql执行器接口

 * @author eleven

 * @see

 * @since

 */


public interface Executor {


    **

     * 执行sql

     * @param configuration

     * @param mappedStatement

     * @param param

     * @return

     */

    <T> List<T> query(Configuration configuration, MappedStatement mappedStatement, Object param);

}



package com.eleven.session;


import com.eleven.config.Configuration;

import com.eleven.config.MappedStatement;


import java.util.List;


/**

 * sql执行器默认实现类

 * @author eleven

 * @see

 * @since

 */


public class SimpleExecutor implements Executor {


    @Override

    public List<Object> query(Configuration configuration, MappedStatement mappedStatement, Object param) {

        此处执行jdbc相关操作

        return null;

    }

}

这里SimpleExecutor中的query方法也就是执行jdbc具体的流程我们留着下一篇撸。最后是SqlSessionFactory和DefaultSqlSessionFactory:

package com.eleven.session;


/**

 * sql执行会话工厂类

 * @author eleven

 * @see

 * @since

 */


public interface SqlSessionFactory {


    **

     * 创建sql执行会话

     * @return

     */

    SqlSession openSqlSession();

}



package com.eleven.session;


import com.eleven.config.Configuration;


/**

 * sql执行会话工厂默认实现类

 * @author eleven

 * @see

 * @since

 */


public class DefaultSqlSessionFactory implements SqlSessionFactory {


    private Configuration configuration;


    public DefaultSqlSessionFactory(Configuration configuration) {

        this.configuration = configuration;

    }


    @Override

    public SqlSession openSqlSession() {

        return new DefaultSqlSession(configuration);

    }

}

那最后我们在我们的dao里面我们就可以直接这样使用了:

public class UserDaoImpl implements UserDao {

private SqlSessionFactory sqlSessionFactory;

public UserDaoImpl(SqlSessionFactory sqlSessionFactory) {

super();

this.sqlSessionFactory = sqlSessionFactory;

}


public UserDaoImpl() {

}


@Override

public User queryUserById(User param) {

// 先创建SqlSession

SqlSession sqlSession = sqlSessionFactory.openSqlSession();

// 调用SqlSession的selectOne方法

String statementId = "test.findUserById";

User user = sqlSession.selectOne(statementId, param);

return user;

}

}

当然,对于SqlSessionFactory的创建你还可以提供一个默认的构建器方便SqlSessionFactory的创建:

package com.eleven.session;



import com.eleven.config.Configuration;

import com.eleven.config.XmlConfigParser;

import com.eleven.util.DocumentUtil;

import org.dom4j.Document;


import java.io.InputStream;


/**

 * sql执行会话工厂构建器

 * @author eleven

 * @see

 * @since

 */


public class SqlSessionFactoryBuilder {


    public SqlSessionFactory build(InputStream inputStream) {

        Document document = DocumentUtil.createDocument(inputStream);

        XmlConfigParser parser = new XmlConfigParser()

        Configuration configuration = 

            parser.parse(document.getRootElement());

        return new DefaultSqlSessionFactory(configuration);

    }

}

与Spring整合的时候就可以将SqlSessionFactoryBuilder提供成SqlSessionFactory依赖注入的源。


文章转载自Alleria Windrunner,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论