1.下载源码
https://github.com/mybatis/mybatis-3/releases 切换分支 3.2.x
2.找一个测试类 BaseDataTest
刚找到代码,一般开源项目都会有test单元测试类的,mybatis测试的类有点多,我们在最外层发现最容易发现这个类BaseDataTest(说个题外话:我也是刚开始看源码,不是很懂,这个飘红不用管,好像是mock的依赖问题。看这个其实停摸不着头脑的,但是鲁迅曾经说过:如果你想干一件事情,不用管他会不会,先假装自己会,顺着自己的思路去做,时机到了,你自然就会了。不要因为恐惧未知,而不去迈出第一步,多大点事,如果你看到这句话了,就一起加油,共勉)
点开我们发现这是一个创建DataSource的工具类,我们在依次向上点方法,这个时候发现随便一个方法有很多地方都用到了,不用管,随便进去一个,我就进去BindingTest。
2.找到关键类:SqlSessionFactoryBuilder
等我们找到BindingTest。如下
我们就发现我们认识的主要的关键类SqlSessionFactoryBuilder。。我们从new SqlSessionFactoryBuilder().build(configuration);点进去build(),这个时候,我们就发现这个BindingTest 是通过 构建Configurtion 去实现sqlSssionFactory.查看这个类的方法,会有很多build构建,都是构建SqlSessionFactory的。像我们常见的demo例子,是通过配置MapperConfig.xml 的方式去构建的。下面我们看一下,我们常用的demo
3.写一个常用mybatis的demo
//这个demo看看就好了,方便理解
static SqlSessionFactory sqlSessionFactory = null;
static {
sqlSessionFactory = MyBatisUtil.getSqlSEssionFactory();
}
@Test
public void testGetUser() throws Exception {
//定义 SqlSession
SqlSession sqlSession =null;
try{
//打开 SqlSession会话
sqlSession= sqlSessionFactory.openSession();
//执行相关代码
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
User user = userMapper.getUser(456l);
System.out.println(JSON.toJSONString(user));
}cacth(Exception ex){
System.err.println(ex.getMessage());
}finally{
//在 finally 语句中确保资源被删除顺利并关闭
if(sqlSession !=null){
sqlSession.close();
}
}
}
--------------------------------------------------------------------MyBatisUtil ------------------------------------------------
public class MyBatisUtil {
private final static SqlSessionFactory sqlSEssionFactory;
static {
String resource = "spring_1_100/config_61_70/mybatis-config.xml";
Reader reader = null;
try {
reader = Resources.getResourceAsReader(resource);
} catch (IOException e) {
e.printStackTrace();
}
sqlSEssionFactory = new SqlSessionFactoryBuilder().build(reader);
}
public static SqlSessionFactory getSqlSEssionFactory(){
return sqlSEssionFactory;
}
}
一个xml 模板(这个xml和前面自定义demo 没关系了,就是看看用的 源码中的案例方便理解src\test\java\org\apache\ibatis\builder\MapperConfig.xml)
<?xml version="1.0" encoding="UTF-8" ?>
<!--
Copyright 2009-2012 the original author or authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<properties resource="databases/blog/blog-derby.properties"/>
<settings>
<setting name="cacheEnabled" value="true"/>
<setting name="lazyLoadingEnabled" value="false"/>
<setting name="multipleResultSetsEnabled" value="true"/>
<setting name="useColumnLabel" value="true"/>
<setting name="useGeneratedKeys" value="false"/>
<setting name="defaultExecutorType" value="SIMPLE"/>
<setting name="defaultStatementTimeout" value="25"/>
</settings>
<typeAliases>
<typeAlias alias="Author" type="domain.blog.Author"/>
<typeAlias alias="Blog" type="domain.blog.Blog"/>
<typeAlias alias="Comment" type="domain.blog.Comment"/>
<typeAlias alias="Post" type="domain.blog.Post"/>
<typeAlias alias="Section" type="domain.blog.Section"/>
<typeAlias alias="Tag" type="domain.blog.Tag"/>
</typeAliases>
<typeHandlers>
<typeHandler javaType="String" jdbcType="VARCHAR" handler="org.apache.ibatis.builder.ExampleTypeHandler"/>
</typeHandlers>
<objectFactory type="org.apache.ibatis.builder.ExampleObjectFactory">
<property name="objectFactoryProperty" value="100"/>
</objectFactory>
<plugins>
<plugin interceptor="org.apache.ibatis.builder.ExamplePlugin">
<property name="pluginProperty" value="100"/>
</plugin>
</plugins>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC">
<property name="" value=""/>
</transactionManager>
<dataSource type="UNPOOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="org/apache/ibatis/builder/AuthorMapper.xml"/>
<mapper resource="org/apache/ibatis/builder/BlogMapper.xml"/>
<mapper resource="org/apache/ibatis/builder/CachedAuthorMapper.xml"/>
<mapper resource="org/apache/ibatis/builder/PostMapper.xml"/>
<mapper resource="org/apache/ibatis/builder/NestedBlogMapper.xml"/>
</mappers>
</configuration>
通过demo,我们知道我们的sqlSEssionFactory 是通过reader数据源去执行,这段关键代码 sqlSEssionFactory = new SqlSessionFactoryBuilder().build(reader);那么,我们再来看SqlSessionFactoryBuilder类构造器中的build方法,可以看到,主要是通过这个方法去实现:
4. XMLConfigBuilder-通过名字大概知道是分析xml的Config构造器
接下来,就可以看到关键方法parser.parse(),点进去看一下,找到关键代码,看看。这每个方法就是一个关键逻辑,由于我是刚开始看,我在网上看了别人的介绍,注释我沾上来了,方便理解。
在这段代码中,看见XMLConfigBuilder 会对xml配置进行解析,通过每个XNode parent 节点,去设置Configuration 对象。感觉不用每个去看,挑个主要的mapper去看看。
就这个,我们随便进个主要的解析看看 mapperParser.parse();
5. XMLMapperBuilder-通过名字大概知道是分析xml的mapper构造器
进入 mapperParser.parse();这个类XMLMapperBuilder的parse()方法,我们继续往下看,此时先贴一个AuthorMapper.xml(源码里面的src\test\java\org\apache\ibatis\builder\AuthorMapper.xml)方便理解
<?xml version="1.0" encoding="UTF-8" ?>
<!--
Copyright 2009-2012 the original author or authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="domain.blog.mappers.AuthorMapper">
<parameterMap id="selectAuthor" type="domain.blog.Author">
<parameter property="id" />
</parameterMap>
<resultMap id="selectAuthor" type="domain.blog.Author">
<id column="id" property="id" />
<result property="username" column="username" />
<result property="password" column="password" />
<result property="email" column="email" />
<result property="bio" column="bio" />
<result property="favouriteSection" column="favourite_section" />
</resultMap>
<resultMap id="selectImmutableAuthor" type="domain.blog.ImmutableAuthor">
<constructor>
<idArg column="id" javaType="_int" />
<arg column="username" javaType="string" />
<arg column="password" javaType="string" />
<arg column="email" javaType="string" />
<arg column="bio" javaType="string" />
<arg column="favourite_section" javaType="domain.blog.Section" />
</constructor>
</resultMap>
<resultMap id="complexAuthorId" type="domain.blog.ComplexImmutableAuthorId">
<constructor>
<idArg column="id" javaType="_int" />
<idArg column="username" javaType="string" />
<idArg column="password" javaType="string" />
<idArg column="email" javaType="string" />
</constructor>
</resultMap>
<resultMap id="selectComplexImmutableAuthor" type="domain.blog.ComplexImmutableAuthor">
<constructor>
<idArg javaType="domain.blog.ComplexImmutableAuthorId"
resultMap="complexAuthorId" />
<arg column="bio" javaType="string" />
<arg column="favourite_section" javaType="domain.blog.Section" />
</constructor>
</resultMap>
<select id="selectAllAuthors" resultType="domain.blog.Author">
select * from author
</select>
<select id="selectAllAuthorsSet" resultType="domain.blog.Author">
select * from author
</select>
<select id="selectAllAuthorsVector" resultType="domain.blog.Author">
select * from author
</select>
<select id="selectAllAuthorsLinkedList" resultType="domain.blog.Author">
select * from author
</select>
<select id="selectAllAuthorsArray" resultType="domain.blog.Author">
select * from author
</select>
<select id="selectComplexAuthors" resultMap="selectComplexImmutableAuthor">
select * from author
</select>
<select id="selectAuthor" parameterMap="selectAuthor" resultMap="selectAuthor">
select id, username, password, email, bio, favourite_section
from author where id = ?
</select>
<select id="selectImmutableAuthor" parameterMap="selectAuthor"
resultMap="selectImmutableAuthor">
select id, username, password, email, bio, favourite_section
from author where id = ?
</select>
<select id="selectAuthorWithInlineParams" parameterType="int"
resultType="domain.blog.Author">
select * from author where id = #{id}
</select>
<insert id="insertAuthor" parameterType="domain.blog.Author">
insert into Author (id,username,password,email,bio)
values (#{id},#{username},#{password},#{email},#{bio})
</insert>
<update id="updateAuthor" parameterType="domain.blog.Author">
update Author
set username=#{username,
javaType=String},
password=#{password},
email=#{email},
bio=#{bio}
where id=#{id}
</update>
<delete id="deleteAuthor" parameterType="int">
delete from Author where id = #{id}
</delete>
<update id="updateAuthorIfNecessary" parameterType="domain.blog.Author">
update Author
<set>
<if test="username != null">username=#{username},</if>
<if test="password != null">password=#{password},</if>
<if test="email != null">email=#{email},</if>
<if test="bio != null">bio=#{bio}</if>
</set>
where id=#{id}
</update>
</mapper>
然后上XMLMapperBuilder的parse()方法:
可以进入第一方法 简单看看configurationElement()
我们发现,XMLMapperBuilder的 MapperBuilderAssistant builderAssistant;这个属性是用来保存每个mapper的属性设置。等到外层的下面三个方法进行加载再到configuration的配置属性中。
6. XMLStatementBuilder-通过名字大概知道是分析xml的语句构造器
通过 buildStatementFromContext(context.evalNodes("select|insert|update|delete"));这个方法,我们进去看看执行sql的配置类 一层一层点进去 找到 XMLStatementBuilder()的这个方法,就是设置sql语句的构造器
通过这个方法一层层设置,最后保存在 configuration中的 protected final Map<String, MappedStatement> mappedStatements = new StrictMap
7. DefaultSqlSessionFactory-默认SqlSessionFactory的实现类
回到前面 sqlSEssionFactory = new SqlSessionFactoryBuilder().build(reader);这个方法构造。当我们设置完configuration,就默认建立一个DefaultSqlSessionFactory默认sqlSesion工厂,里面关键参数configuration。
================================================================= [手把手看mybatis源码(3.2.x)-2]
回复