Summary of Mybatis implementation process

Summary of experience

Today I wrote a simple version of Mybatis following the video, hereby record the details and insights.

Implementation steps

1. First look at the main method, which objects are needed to implement a Mybatis framework.

 public static void main(String[] args)throws Exception {
    
    
       // 1.读取配置文件
       InputStream in = Resources.getResourcesAsStream("SqlMapConfig.xml");
       // 2.创建SQLSessionFaction工厂
       SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
       SqlSessionFactory factory = builder.build(in);
       // 3.用SQLSession工厂生产SQLSession对象0
       SqlSession session = factory.openSession();
       // 4.使用SQLSession创建Dao接口的代理对象
       IAccountDao accountDao = (IAccountDao) session.getMapper(IAccountDao.class);
       // 5.使用代理对象执行方法
       List<Account> accounts = accountDao.findAllAccount();
       for (Account account : accounts) {
    
    
           System.out.println(account);
       }
       // 6.释放资源
       session.close();
       in.close();
   }

Analysis: The
first line of code requires a Resource object, and in this class, a method named getResourcesAsStream with a return value type of InputStream is required.
The second line of code obviously requires a SqlSessionFactoryBuilder object.
The third line of code analyzes that a SqlSessionFactory object is needed, and this object is created through the build method of the SqlSessionFactoryBuilder object and an InputStream parameter.
The fourth line of code uses a SqlSession object, and this object is created by the openSession method of S qlSessionFactory.
The fifth line of code, through the getMapper method of SqlSession and the bytecode file of an object, it can be seen that generics are used here to support the same method to return different mappers.

Summary: At least the objects Mybatis needs to use: 1.Resource, 2.SqlSessionFactoryBuilder, 3.SqlSessionFactory, 4.SqlSession.
In addition, xml file parsing class (XMLConfigBuilder), SQL statement execution class (Executor), database connection attribute class (Configuration),
registration driver acquisition connection class (DataSourceUtil), dynamic proxy interface InvocationHandler interface implementation class ( MapperProxy), Sql statement object package mapping class (Mapper), but I still need to spend some time digesting the Executor and XMLConfigBuilder classes. The related tool classes and configuration classes will not be exhibited here, and will be updated later.
At least the method used:

  1. Resources对象 的 public static InputStream getResourcesAsStream(String filePath){}
  2. SqlSessionFactoryBuilder 的 public SqlSessionFactory build(InputStream config){}
  3. Sqlsesson 的 SqlSession openSession();
  4. SqlSession's <T> T getMapper(Class< T> daoIntegerClass);
    General process: Resource class reads the configuration file, converts the content of the configuration file into a byte input stream, and then uses the creator mode to create a SqlSessionFactory using the byte stream (Factory mode), then use the factory to produce the SqlSession, and finally obtain the Mapper object through the Session.
    Second, implement specific classes and interfaces
    1. Resource class
public class Resources {
    
    
    //getResourcesAsStream方法,返回一个字节输入流
    public static InputStream getResourcesAsStream(String filePath){
    
    
        //反射机制,类加载器获取方法
        return Resources.class.getClassLoader().getResourceAsStream(filePath);
    }
}

2.SqlSessionFactoryBuilder class

public class SqlSessionFactoryBuilder {
    
    
    //创建SqlSessionFactory对象的方法
    public SqlSessionFactory build(InputStream config){
    
    
        //解析xml文件获取连接信息,并封装进Configuration对象中
        Configuration cfg = XMLConfigBuilder.loadConfiguration(config);
        //返回一个SqlSessionFactory的实现类对象
        return new DefaultSqlSessionFactoryImpl(cfg);
    }
}

3. SqlSessionFactory interface and its implementation class

public interface SqlSessionFactory {
    
    
    SqlSession openSession();
}
public class DefaultSqlSessionFactoryImpl implements SqlSessionFactory{
    
    
    private Configuration cfg;

    public DefaultSqlSessionFactoryImpl(Configuration cfg) {
    
    
        this.cfg = cfg;
    }

    @Override
    public SqlSession openSession() {
    
    
    	//SqlSession的实现类
        return new DefaultSqlSessionImpl(cfg);
    }
}

4. SqlSession interface and its implementation class and dynamic proxy interface implementation class

public interface SqlSession {
    
    

    <T> T getMapper(Class<T> daoIntegerClass);

    void close();
}
public class DefaultSqlSessionImpl implements SqlSession {
    
    

    private Configuration cfg;
    private Connection connection;

    public DefaultSqlSessionImpl(Configuration cfg) {
    
    
        this.cfg = cfg;
        connection = DataSourceUtil.getConnection(cfg);
    }

    @Override
    public <T> T getMapper(Class<T> daoIntegerClass) {
    
    
		//Proxy是动态代理技术的实现,MapperProxy类实现了InvocationHandler接口,做到了方法增强
        return (T) Proxy.newProxyInstance(daoIntegerClass.getClassLoader(),new Class[]{
    
    daoIntegerClass},
                new MapperProxy(cfg.getMappers(),connection));
    }

    @Override
    public void close() {
    
    
        if (connection != null){
    
    
            try {
    
    
                connection.close();
            } catch (SQLException e) {
    
    
                e.printStackTrace();
            }
        }
    }
}
public class MapperProxy implements InvocationHandler{
    
    
    private Map<String,Mapper> mappers;
    private Connection conn;

    public MapperProxy(Map<String, Mapper> mappers, Connection conn) {
    
    
        this.mappers = mappers;
        this.conn = conn;
    }

    public MapperProxy(Map<String, Mapper> mappers) {
    
    
        this.mappers = mappers;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    
    
        //获取方法名
        String methodName = method.getName();
        //获取方法所在的类名
        String className = method.getDeclaringClass().getName();
        String key = className+"."+methodName;
        Mapper mapper = mappers.get(key);
        if (mapper == null){
    
    
            throw new IllegalArgumentException("传入参数有误");
        }
        return new Executor().selectList(mapper,conn);
    }
}

Guess you like

Origin blog.csdn.net/TreeCode/article/details/108037796