mybatis_helloworld(2)_源码
2016-07-27 12:16
495 查看
摘录自:http://blog.csdn.net/y172158950/article/details/16982123
在helloworld(1)中,分析了insert一条数据的流程,现在分析下源码:
[java] view plain copy
public static void main(String args[]) throws IOException {
String resource = "com/test/configuration.xml";//获得xml(Mybatis)数据库连接的连接
Reader reader = Resources.getResourceAsReader(resource);//读取里面的文件
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder()
.build(reader);//创建session工厂
SqlSession session = sessionFactory.openSession();//打开session
new Test1().insert(session);
}
b)Resources类:定义了一系列的静态方法,用于获取资源(ClassLoader,URL,InputStream,Read,File,Properties,Charset)
c)我们用到的getResourceAsReader,getResourceAsStream方法
[java] view plain copy
<p> public static Reader getResourceAsReader(String resource)
throws IOException
{
Reader reader;</p><p>· //利用InputStream构造Reader
if(charset == null)
reader = new InputStreamReader(getResourceAsStream(resource));
else
reader = new InputStreamReader(getResourceAsStream(resource), charset);
return reader;
}</p><p> </p><p> public static InputStream getResourceAsStream(String resource)
throws IOException
{</p><p> //调用重载方法
return getResourceAsStream(null, resource);
}</p><p> </p><p> public static InputStream getResourceAsStream(ClassLoader loader, String resource)
throws IOException
{</p><p> //调用ClassLoaderWrapper类的方法,利用ClassLoader获取资源
InputStream in = classLoaderWrapper.getResourceAsStream(resource, loader);
if(in == null)
throw new IOException((new StringBuilder()).append("Could not find resource ").append(resource).toString());
else
return in;
}</p>
d)ClassLoaderWrapper类:封装了一个ClassLoader数组,通过ClassLoader获取资源
e)我们用到的getResourceAsStream,getClassLoaders方法
[java] view plain copy
public InputStream getResourceAsStream(String resource, ClassLoader classLoader)
{
return getResourceAsStream(resource, getClassLoaders(classLoader));
}
ClassLoader[] getClassLoaders(ClassLoader classLoader)
{
return (new ClassLoader[] { //构建新的ClassLoader列表,包含用户创建及默认
classLoader, defaultClassLoader, Thread.currentThread().getContextClassLoader(), getClass().getClassLoader(), systemClassLoader});
}
InputStream getResourceAsStream(String resource, ClassLoader classLoader[])
{
ClassLoader arr$[] = classLoader;
int len$ = arr$.length;
for(int i$ = 0; i$ < len$; i$++) //遍历ClassLoader数组,当某一个Loader成功构建资源则返回
{
ClassLoader cl = arr$[i$];
if(null == cl)
continue;
InputStream returnValue = cl.getResourceAsStream(resource);
if(null == returnValue)
returnValue = cl.getResourceAsStream((new StringBuilder()).append("/").append(resource).toString());
if(null != returnValue)
return returnValue;
}
return null;
}
[java] view plain copy
public interface SqlSessionFactory
{
//定义了一系列获取Session的方法,获取Configuration的方法
public abstract SqlSession openSession();
public abstract SqlSession openSession(boolean flag);
public abstract SqlSession openSession(Connection connection);
public abstract SqlSession openSession(TransactionIsolationLevel transactionisolationlevel);
public abstract SqlSession openSession(ExecutorType executortype);
public abstract SqlSession openSession(ExecutorType executortype, boolean flag);
public abstract SqlSession openSession(ExecutorType executortype, TransactionIsolationLevel transactionisolationlevel);
public abstract SqlSession openSession(ExecutorType executortype, Connection connection);
public abstract Configuration getConfiguration();
}
b) SqlSessionFactory接口构建
i. SqlSessionFactoryBuilder类:构建SqlSessionFactory
ii. 我们使用的方法:build
[java] view plain copy
public SqlSessionFactory build(Reader reader)
{
//调用重载方法
return build(reader, null, null);
}
public SqlSessionFactory build(Reader reader, String environment, Properties properties)
{
try
{
SqlSessionFactory sqlsessionfactory;
try
{
//根据reader封装XMLConfig相关信息
XMLConfigBuilder parser = new XMLConfigBuilder(reader, environment, properties);
//调用重载方法
sqlsessionfactory = build(parser.parse());
}
catch(Exception e)
{
throw ExceptionFactory.wrapException("Error building SqlSession.", e);
}
return sqlsessionfactory;
}
finally
{
ErrorContext.instance().reset();
try
{
reader.close();
}
catch(IOException e) { }
}
}
public SqlSessionFactory build(Configuration config)
{
//依据配置信息构建默认的SqlSessionFactory实现
return new DefaultSqlSessionFactory(config);
}
c) XMLConfigBuilder类:解析XML配置文件
i. 用到的主要方法:parse,parseConfiguration(就是按XML结构顺序解析,分别获取配置[SAX解析]);将数据封装到父类的configuration对象中
[java] view plain copy
public Configuration parse()
{
if(parsed)
{
throw new BuilderException("Each MapperConfigParser can only be used once.");
} else
{
parsed = true;
parseConfiguration(parser.evalNode("/configuration")); //XML文件的根目录
return configuration;
}
}
private void parseConfiguration(XNode root)
{
try
{
typeAliasesElement(root.evalNode("typeAliases")); //解析typeAliases
pluginElement(root.evalNode("plugins"));
objectFactoryElement(root.evalNode("objectFactory"));
objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));
propertiesElement(root.evalNode("properties"));
settingsElement(root.evalNode("settings"));
environmentsElement(root.evalNode("environments")); //数据库配置
typeHandlerElement(root.evalNode("typeHandlers"));
mapperElement(root.evalNode("mappers")); //解析sql语句配置文件
}
catch(Exception e)
{
throw new BuilderException((new StringBuilder()).append("Error parsing SQL Mapper Configuration. Cause: ").append(e).toString(), e);
}
}
d)Configuration类:基本就是封装一系列的数据;看一下成员变量
[java] view plain copy
protected Environment environment;
protected boolean lazyLoadingEnabled;
protected boolean aggressiveLazyLoading;
protected boolean multipleResultSetsEnabled;
protected boolean useGeneratedKeys;
protected boolean useColumnLabel;
protected boolean cacheEnabled;
protected Integer defaultStatementTimeout;
protected ExecutorType defaultExecutorType;
protected AutoMappingBehavior autoMappingBehavior;
protected Properties variables;
protected ObjectFactory objectFactory;
protected ObjectWrapperFactory objectWrapperFactory;
protected MapperRegistry mapperRegistry;
protected final InterceptorChain interceptorChain;
protected final TypeHandlerRegistry typeHandlerRegistry;
protected final TypeAliasRegistry typeAliasRegistry;
protected final Map mappedStatements;
protected final Map caches;
protected final Map resultMaps;
protected final Map parameterMaps;
protected final Map keyGenerators;
protected final Set loadedResources;
protected final Map sqlFragments;
protected final Collection incompleteStatements;
protected final Collection incompleteCacheRefs;
protected final Map cacheRefMap;
e)DefaultSqlSessionFactory类:SqlSessionFactory接口实现类,并持有一个Configuration对象;我们实现获取SqlSeesion对象应用的此类的方法。
public SqlSession openSession()
{
return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, false);
}
private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit)
{
Connection connection = null;
try
{
DefaultSqlSession defaultsqlsession;
try
{
Environment environment = configuration.getEnvironment();
//获取javax.sql.DataSource
DataSource dataSource = getDataSourceFromEnvironment(environment);
TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
//获取java.sql.Connection
connection = dataSource.getConnection();
if(level != null)
connection.setTransactionIsolation(level.getLevel());
connection = wrapConnection(connection);
//一系列的封装,把Connection包装成了DefaultSqlSession(SqlSession的实现类)
org.apache.ibatis.transaction.Transaction tx = transactionFactory.newTransaction(connection, autoCommit);
org.apache.ibatis.executor.Executor executor = configuration.newExecutor(tx, execType);
defaultsqlsession = new DefaultSqlSession(configuration, executor, autoCommit);
}
catch(Exception e)
{
closeConnection(connection);
throw ExceptionFactory.wrapException((new StringBuilder()).append("Error opening session. Cause: ").append(e).toString(), e);
}
return defaultsqlsession;
}
finally
{
ErrorContext.instance().reset();
}
}
public int insert(String statement, Object parameter)
{
return update(statement, parameter);
}
public int update(String statement, Object parameter)
{
try
{
int i;
try
{
dirty = true;
//根据Mapper.xml配置文件中的id找到Sql语句
org.apache.ibatis.mapping.MappedStatement ms = configuration.getMappedStatement(statement);
//这个执行器是不是见过?构建DefaultSqlSession时传过来的
// org.apache.ibatis.executor.Executor executor = configuration.newExecutor(tx, execType);
i = executor.update(ms, wrapCollection(parameter));
}
catch(Exception e)
{
throw ExceptionFactory.wrapException((new StringBuilder()).append("Error updating database. Cause: ").append(e).toString(), e);
}
return i;
}
finally
{
ErrorContext.instance().reset();
}
}
a) 找一下executor,看看其update方法
i. 调用哪个executor?
[java] view plain copy
public Executor newExecutor(Transaction transaction, ExecutorType executorType)
{
executorType = executorType != null ? executorType : defaultExecutorType; //我们使用的是默认的Type(SIMPLE)
executorType = executorType != null ? executorType : ExecutorType.SIMPLE;
Executor executor;
if(ExecutorType.BATCH == executorType)
executor = new BatchExecutor(this, transaction);
else
if(ExecutorType.REUSE == executorType)
executor = new ReuseExecutor(this, transaction);
else
executor = new SimpleExecutor(this, transaction);
if(cacheEnabled)
executor = new CachingExecutor(executor);
executor = (Executor)interceptorChain.pluginAll(executor);
return executor;
}
ii. SimpleExecutor的update方法实现
[java] view plain copy
//父类BaseExecutor的update方法,调用了doUpdate方法
public int update(MappedStatement ms, Object parameter)
throws SQLException
{
ErrorContext.instance().resource(ms.getResource()).activity("executing an update").object(ms.getId());
if(closed)
{
throw new ExecutorException("Executor was closed.");
} else
{
clearLocalCache();
return doUpdate(ms, parameter);
}
}
//子类SimpleExecutor重写了doUpdate方法
public int doUpdate(MappedStatement ms, Object parameter)
throws SQLException
{
//java.sql.Statement
Statement stmt = null;
int i;
try
{
Configuration configuration = ms.getConfiguration();
StatementHandler handler = configuration.newStatementHandler(this, ms, parameter, RowBounds.DEFAULT, null);
//大概就是拼Sql,生成对应的Statement,执行Sql,封装数据了(这块比较复杂,下次再看了)
stmt = prepareStatement(handler);
i = handler.update(stmt);
}
finally
{
closeStatement(stmt);
}
return i;
}
看了一回源码,也感觉高端大气上档次了,下次画个图
在helloworld(1)中,分析了insert一条数据的流程,现在分析下源码:
[java] view plain copy
public static void main(String args[]) throws IOException {
String resource = "com/test/configuration.xml";//获得xml(Mybatis)数据库连接的连接
Reader reader = Resources.getResourceAsReader(resource);//读取里面的文件
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder()
.build(reader);//创建session工厂
SqlSession session = sessionFactory.openSession();//打开session
new Test1().insert(session);
}
1. XML文件资源的获取
a)包路径:org.apache.ibatis.iob)Resources类:定义了一系列的静态方法,用于获取资源(ClassLoader,URL,InputStream,Read,File,Properties,Charset)
c)我们用到的getResourceAsReader,getResourceAsStream方法
[java] view plain copy
<p> public static Reader getResourceAsReader(String resource)
throws IOException
{
Reader reader;</p><p>· //利用InputStream构造Reader
if(charset == null)
reader = new InputStreamReader(getResourceAsStream(resource));
else
reader = new InputStreamReader(getResourceAsStream(resource), charset);
return reader;
}</p><p> </p><p> public static InputStream getResourceAsStream(String resource)
throws IOException
{</p><p> //调用重载方法
return getResourceAsStream(null, resource);
}</p><p> </p><p> public static InputStream getResourceAsStream(ClassLoader loader, String resource)
throws IOException
{</p><p> //调用ClassLoaderWrapper类的方法,利用ClassLoader获取资源
InputStream in = classLoaderWrapper.getResourceAsStream(resource, loader);
if(in == null)
throw new IOException((new StringBuilder()).append("Could not find resource ").append(resource).toString());
else
return in;
}</p>
d)ClassLoaderWrapper类:封装了一个ClassLoader数组,通过ClassLoader获取资源
e)我们用到的getResourceAsStream,getClassLoaders方法
[java] view plain copy
public InputStream getResourceAsStream(String resource, ClassLoader classLoader)
{
return getResourceAsStream(resource, getClassLoaders(classLoader));
}
ClassLoader[] getClassLoaders(ClassLoader classLoader)
{
return (new ClassLoader[] { //构建新的ClassLoader列表,包含用户创建及默认
classLoader, defaultClassLoader, Thread.currentThread().getContextClassLoader(), getClass().getClassLoader(), systemClassLoader});
}
InputStream getResourceAsStream(String resource, ClassLoader classLoader[])
{
ClassLoader arr$[] = classLoader;
int len$ = arr$.length;
for(int i$ = 0; i$ < len$; i$++) //遍历ClassLoader数组,当某一个Loader成功构建资源则返回
{
ClassLoader cl = arr$[i$];
if(null == cl)
continue;
InputStream returnValue = cl.getResourceAsStream(resource);
if(null == returnValue)
returnValue = cl.getResourceAsStream((new StringBuilder()).append("/").append(resource).toString());
if(null != returnValue)
return returnValue;
}
return null;
}
2. 构建SqlSessionFactory,初始化资源
a) SqlSessionFactory接口介绍[java] view plain copy
public interface SqlSessionFactory
{
//定义了一系列获取Session的方法,获取Configuration的方法
public abstract SqlSession openSession();
public abstract SqlSession openSession(boolean flag);
public abstract SqlSession openSession(Connection connection);
public abstract SqlSession openSession(TransactionIsolationLevel transactionisolationlevel);
public abstract SqlSession openSession(ExecutorType executortype);
public abstract SqlSession openSession(ExecutorType executortype, boolean flag);
public abstract SqlSession openSession(ExecutorType executortype, TransactionIsolationLevel transactionisolationlevel);
public abstract SqlSession openSession(ExecutorType executortype, Connection connection);
public abstract Configuration getConfiguration();
}
b) SqlSessionFactory接口构建
i. SqlSessionFactoryBuilder类:构建SqlSessionFactory
ii. 我们使用的方法:build
[java] view plain copy
public SqlSessionFactory build(Reader reader)
{
//调用重载方法
return build(reader, null, null);
}
public SqlSessionFactory build(Reader reader, String environment, Properties properties)
{
try
{
SqlSessionFactory sqlsessionfactory;
try
{
//根据reader封装XMLConfig相关信息
XMLConfigBuilder parser = new XMLConfigBuilder(reader, environment, properties);
//调用重载方法
sqlsessionfactory = build(parser.parse());
}
catch(Exception e)
{
throw ExceptionFactory.wrapException("Error building SqlSession.", e);
}
return sqlsessionfactory;
}
finally
{
ErrorContext.instance().reset();
try
{
reader.close();
}
catch(IOException e) { }
}
}
public SqlSessionFactory build(Configuration config)
{
//依据配置信息构建默认的SqlSessionFactory实现
return new DefaultSqlSessionFactory(config);
}
c) XMLConfigBuilder类:解析XML配置文件
i. 用到的主要方法:parse,parseConfiguration(就是按XML结构顺序解析,分别获取配置[SAX解析]);将数据封装到父类的configuration对象中
[java] view plain copy
public Configuration parse()
{
if(parsed)
{
throw new BuilderException("Each MapperConfigParser can only be used once.");
} else
{
parsed = true;
parseConfiguration(parser.evalNode("/configuration")); //XML文件的根目录
return configuration;
}
}
private void parseConfiguration(XNode root)
{
try
{
typeAliasesElement(root.evalNode("typeAliases")); //解析typeAliases
pluginElement(root.evalNode("plugins"));
objectFactoryElement(root.evalNode("objectFactory"));
objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));
propertiesElement(root.evalNode("properties"));
settingsElement(root.evalNode("settings"));
environmentsElement(root.evalNode("environments")); //数据库配置
typeHandlerElement(root.evalNode("typeHandlers"));
mapperElement(root.evalNode("mappers")); //解析sql语句配置文件
}
catch(Exception e)
{
throw new BuilderException((new StringBuilder()).append("Error parsing SQL Mapper Configuration. Cause: ").append(e).toString(), e);
}
}
d)Configuration类:基本就是封装一系列的数据;看一下成员变量
[java] view plain copy
protected Environment environment;
protected boolean lazyLoadingEnabled;
protected boolean aggressiveLazyLoading;
protected boolean multipleResultSetsEnabled;
protected boolean useGeneratedKeys;
protected boolean useColumnLabel;
protected boolean cacheEnabled;
protected Integer defaultStatementTimeout;
protected ExecutorType defaultExecutorType;
protected AutoMappingBehavior autoMappingBehavior;
protected Properties variables;
protected ObjectFactory objectFactory;
protected ObjectWrapperFactory objectWrapperFactory;
protected MapperRegistry mapperRegistry;
protected final InterceptorChain interceptorChain;
protected final TypeHandlerRegistry typeHandlerRegistry;
protected final TypeAliasRegistry typeAliasRegistry;
protected final Map mappedStatements;
protected final Map caches;
protected final Map resultMaps;
protected final Map parameterMaps;
protected final Map keyGenerators;
protected final Set loadedResources;
protected final Map sqlFragments;
protected final Collection incompleteStatements;
protected final Collection incompleteCacheRefs;
protected final Map cacheRefMap;
e)DefaultSqlSessionFactory类:SqlSessionFactory接口实现类,并持有一个Configuration对象;我们实现获取SqlSeesion对象应用的此类的方法。
3. 回过头来,再看看SqlSession session = sessionFactory.openSession();这行代码的实现
[java] view plain copypublic SqlSession openSession()
{
return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, false);
}
private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit)
{
Connection connection = null;
try
{
DefaultSqlSession defaultsqlsession;
try
{
Environment environment = configuration.getEnvironment();
//获取javax.sql.DataSource
DataSource dataSource = getDataSourceFromEnvironment(environment);
TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
//获取java.sql.Connection
connection = dataSource.getConnection();
if(level != null)
connection.setTransactionIsolation(level.getLevel());
connection = wrapConnection(connection);
//一系列的封装,把Connection包装成了DefaultSqlSession(SqlSession的实现类)
org.apache.ibatis.transaction.Transaction tx = transactionFactory.newTransaction(connection, autoCommit);
org.apache.ibatis.executor.Executor executor = configuration.newExecutor(tx, execType);
defaultsqlsession = new DefaultSqlSession(configuration, executor, autoCommit);
}
catch(Exception e)
{
closeConnection(connection);
throw ExceptionFactory.wrapException((new StringBuilder()).append("Error opening session. Cause: ").append(e).toString(), e);
}
return defaultsqlsession;
}
finally
{
ErrorContext.instance().reset();
}
}
4. insert数据的实现
[java] view plain copypublic int insert(String statement, Object parameter)
{
return update(statement, parameter);
}
public int update(String statement, Object parameter)
{
try
{
int i;
try
{
dirty = true;
//根据Mapper.xml配置文件中的id找到Sql语句
org.apache.ibatis.mapping.MappedStatement ms = configuration.getMappedStatement(statement);
//这个执行器是不是见过?构建DefaultSqlSession时传过来的
// org.apache.ibatis.executor.Executor executor = configuration.newExecutor(tx, execType);
i = executor.update(ms, wrapCollection(parameter));
}
catch(Exception e)
{
throw ExceptionFactory.wrapException((new StringBuilder()).append("Error updating database. Cause: ").append(e).toString(), e);
}
return i;
}
finally
{
ErrorContext.instance().reset();
}
}
a) 找一下executor,看看其update方法
i. 调用哪个executor?
[java] view plain copy
public Executor newExecutor(Transaction transaction, ExecutorType executorType)
{
executorType = executorType != null ? executorType : defaultExecutorType; //我们使用的是默认的Type(SIMPLE)
executorType = executorType != null ? executorType : ExecutorType.SIMPLE;
Executor executor;
if(ExecutorType.BATCH == executorType)
executor = new BatchExecutor(this, transaction);
else
if(ExecutorType.REUSE == executorType)
executor = new ReuseExecutor(this, transaction);
else
executor = new SimpleExecutor(this, transaction);
if(cacheEnabled)
executor = new CachingExecutor(executor);
executor = (Executor)interceptorChain.pluginAll(executor);
return executor;
}
ii. SimpleExecutor的update方法实现
[java] view plain copy
//父类BaseExecutor的update方法,调用了doUpdate方法
public int update(MappedStatement ms, Object parameter)
throws SQLException
{
ErrorContext.instance().resource(ms.getResource()).activity("executing an update").object(ms.getId());
if(closed)
{
throw new ExecutorException("Executor was closed.");
} else
{
clearLocalCache();
return doUpdate(ms, parameter);
}
}
//子类SimpleExecutor重写了doUpdate方法
public int doUpdate(MappedStatement ms, Object parameter)
throws SQLException
{
//java.sql.Statement
Statement stmt = null;
int i;
try
{
Configuration configuration = ms.getConfiguration();
StatementHandler handler = configuration.newStatementHandler(this, ms, parameter, RowBounds.DEFAULT, null);
//大概就是拼Sql,生成对应的Statement,执行Sql,封装数据了(这块比较复杂,下次再看了)
stmt = prepareStatement(handler);
i = handler.update(stmt);
}
finally
{
closeStatement(stmt);
}
return i;
}
看了一回源码,也感觉高端大气上档次了,下次画个图
相关文章推荐
- (二分)HDU 1969 pie
- 需求变更的控制及管理
- 我的血泪史
- #CentOS on Mac#2.加入系统调用
- HDU 1361 Parencodings
- 十大销售管理软件排行榜
- copy_from_user()
- hdu 1003 Max Sum
- JAVA之TCP网络程序
- AutoItLibrary安装和常见问题解决
- 在头文件中加入#program once
- Xms Xmx PermSize MaxPermSize 区别
- 部分函数的递归与迭代(非递归)实现
- uva11045
- 51nod 最长公共子序列问题(动态规划)(LCS)(递归)
- 将引用的多个jar包通过MANIFEST.MF打包成一个jar
- 2001 计算两点间的距离
- 从零开始的Android新项目4 - Dagger2篇
- JScript中的条件注释详解(转载自网络)
- 房贷计算器java版