mybatis简介
mybatis是一款优秀的半自动化持久层框架,它支持定制化SQL,存储过程以及高级映射。Mybatis避免了几乎所有的JDBC代码和手动设置参数获取结果集。Mybatis可以使用简单的XML或者注解来配置和映射原生信息,将java的pojo映射成数据库中的记录。
优点:SQL统一维护配置文件中,方便管理维护,半自动化,插件支持,简单易学
接下来我们对Mybits的底层代码进行解析
流程总结
1、读取Mybatis配置文件信息
2、获取SqlSessionFactory
3、获取session
4、操作mapper接口
主要代码
// 1.定义mybatis_config文件地址 String resources = "mybatis_config.xml"; // 2.获取InputStreamReaderIo流 Reader reader = Resources.getResourceAsReader(resources); // 3.获取SqlSessionFactory SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader); // 4.获取Session SqlSession sqlSession = sqlSessionFactory.openSession(); // 5.操作Mapper接口 UserMapper mapper = sqlSession.getMapper(UserMapper.class);
1、读取Mybatis配置文件信息
首先调用getResourceAsStream(String resource)方法,传入mybatis-config.xml
然后该方法里面又调用了本类中的两个参数的getResuorceAsStream(ClassLoader loader,String resource)方法。
通过classLoaderWrapper.getResourceAsStream(resource, loader)方法来获取流,
再调用getResourceAsStream(resource, loader)方法,然后再调用了本类中的getResourceAsStream(String resource, ClassLoader[ ] classLoader)方法
最后判断类加载器中所读的流是否为null,如果不为null,则返回InputStream对象。
InputStream getResourceAsStream(String resource, ClassLoader[] classLoader) {
for (ClassLoader cl : classLoader) {
if (null != cl) {
InputStream returnValue = cl.getResourceAsStream(resource)
if (null == returnValue) {
returnValue = cl.getResourceAsStream("/" + resource);
}
if (null != returnValue) {
return returnValue;
}
}
}
return null;
}
2、获取SqlSessionFactory
首先创建SqlSessionFactoryBuilder对象;然后调用build(InputStream inputStream)方法;
再调用本类中的build(InputStream inputStream, String environment, Properties properties),
然后创建解析器parser,通过Xpath解析的方式去解析mybatis-config.xml 文件,保存到configuration对象中 ,
后返回DefaultSqlSessionFactory对象。
3、获取session
首先调用openSession()方法,再去调用本类中的openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit)方法。
接而创建事务tx,获取environment信息,通过environment构建出transactionFactory事务工厂,通过事务工厂对事物进行设置。
newExecutor(),根据Executor在全局配置中的类型,创建出对应的执行器,
最后返回 DefaultSqlSession对象。
SqlSession session = sqlsessionfactor.openSession();
private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
Transaction tx = null;
try {
final Environment environment = configuration.getEnvironment();
final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
final Executor executor = configuration.newExecutor(tx, execType);
return new DefaultSqlSession(configuration, executor, autoCommit);
} catch (Exception e) {
closeTransaction(tx); // may have fetched a connection so lets call close()
throw ExceptionFactory.wrapException("Error opening session. Cause: " + e, e);
} finally {
ErrorContext.instance().reset();
}
}
4、操作mapper接口
调用DefaultSqlSession中getMapper(Class<T> type)方法。
再调用Configuration中的getMapper(Class<T> type, SqlSession sqlSession)方法。
再调用MapperRegistry中的getMapper(Class<T> type, SqlSession sqlSession)方法。
调用mapperProxyFactory中的newInstance(SqlSession sqlSession)方法获取一个MapperProxy对象mapperProxy。
根据mapperProxy调用newInstance(MapperProxy<T> mapperProxy),创建出MapperProxy的代理对象并且返回。
UserMapper mapper = session.getMapper(UserMapper.class);
public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
final MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory<T>) knownMappers.get(type);
if (mapperProxyFactory == null)
throw new BindingException("Type " + type + " is not known to the MapperRegistry.");
try {
return mapperProxyFactory.newInstance(sqlSession);
} catch (Exception e) {
throw new BindingException("Error getting mapper instance. Cause: " + e, e);
}
}
protected T newInstance(MapperProxy<T> mapperProxy) {
return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);
}
public T newInstance(SqlSession sqlSession) {
final MapperProxy<T> mapperProxy = new MapperProxy<T>(sqlSession, mapperInterface, methodCache);
return newInstance(mapperProxy);