mybatis-config.xml
UserMapper.xml
select id as id,name as name , address as address ,age as age from user where id = 4
UserMapper
package com.wxz.mapper;
import com.wxz.domain.User;
import java.util.List;
public interface UserMapper {
public User selectOne();
public List selectAll();
}
测试类
package com.wxz;
import com.wxz.domain.User;
import com.wxz.mapper.UserMapper;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.IOException;
import java.io.InputStream;
public class Test {
public static void main(String[] args) {
InputStream inputStream = null;
try {
inputStream = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
User user = sqlSession.selectOne("com.wxz.mapper.UserMapper.selectOne");
// UserMapper userDao = sqlSession.getMapper(UserMapper.class);
// User user = userDao.selectOne();
System.out.println(user);
} catch (IOException e) {
e.printStackTrace();
}
}
}
第一步,解析mybatis-config.xml文件
XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
找到mybatis-config.xml中的根节点configuration
解析配置文件中所有的节点
找到mappers节点中resource再去解析UserMapper.xml文件
开始解析UserMapper.xml文件中的mapper节点
namespace==boundType,并且将namespace放进configration类loadedResources中
将接口放入
将接口(namespace)放进configration 类mapperRegistry中 knownMappers
Map
为接口创建代理类,(com.wxz.mapper.UserMapper)放入map容器中,使用接口的class对象作为key(UserMapper.class),value值为 MapperProxyFactory>
查询的时候,UserMapper.class作为参数,如果namespace和接口的全路径不一致,则抛出绑定异常
Map
在MapperProxyFactory>中又创建一个map,将方法名称作为key,value值为MapperMethodInvoker,包含sql的标签,包含sql命令的类型,id值
总之,将接口的代理类放入mapperRegistry中,
同时将namespace+id 作为key,valueMappedStatement 放入mappedStatements中
MapmappedStatements;
第二步:将xml信息转化为Configuration类对象
第三步:将Configuration类对象作为参数传入,创建一个SqlSessionFactory对象
public SqlSessionFactory build(Configuration config) {
return new DefaultSqlSessionFactory(config);
}
第四步:实际上 new DefaultSqlSessionFactory(config)
第五步:根据sqlSessionFactory获取sqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
第六步:具体的数据库操作
第一种:使用(namespace+id)作为key,去mappedStatements中查询
publicT selectOne(String statement, Object parameter) { List list = this.selectList(statement, parameter); if (list.size() == 1) { return list.get(0); } else if (list.size() > 1) { throw new TooManyResultsException("Expected one result (or null) to be returned by selectOne(), but found: " + list.size()); } else { return null; } }
statement就是namespace+id 在前面就将namespace+id 作为key放入map中,value是mappedStatent根据key查询mappedStatent
第七步:根据statement找到对应的MappedStatement MappedStatement ms = this.configuration.getMappedStatement(statement);
第八步:调用executor去查询,从MappedStatement获取到sql语句
var6 = this.executor.query(ms, this.wrapCollection(parameter), rowBounds, handler); BoundSql boundSql = ms.getBoundSql(parameterObject);
第九步:查询缓存,从缓存中获取,若缓存没有,则查询数据库,再放入缓存中
第十步:根据结果映射关系将查询的结果转化为具体的指定的类 ,此处将查询到的结果转化为User对象
第二种:使用代理(UserMapper.class)作为key,去mapperRegistry中查询
上面已经说明了代理的实现,mybatis源码分析到此结束
根据接口创建代理类(com.wxz.mapper.UserMapper)放入容器中,使用接口的class对象作为key(UserMapper.class),value值为 MapperProxyFactory>
private final Map, MapperProxyFactory>> knownMappers = new HashMap();
Mabatis中 sql语句的构建
public String parse(String text) {
if (text != null && !text.isEmpty()) {
int start = text.indexOf(this.openToken);
if (start == -1) {
return text;
} else {
char[] src = text.toCharArray();
int offset = 0;
StringBuilder builder = new StringBuilder();
StringBuilder expression = null;
do {
if (start > 0 && src[start - 1] == '\') {
builder.append(src, offset, start - offset - 1).append(this.openToken);
offset = start + this.openToken.length();
} else {
if (expression == null) {
expression = new StringBuilder();
} else {
expression.setLength(0);
}
builder.append(src, offset, start - offset);
offset = start + this.openToken.length();
int end;
for(end = text.indexOf(this.closeToken, offset); end > -1; end = text.indexOf(this.closeToken, offset)) {
if (end <= offset || src[end - 1] != '\') {
expression.append(src, offset, end - offset);
break;
}
expression.append(src, offset, end - offset - 1).append(this.closeToken);
offset = end + this.closeToken.length();
}
if (end == -1) {
builder.append(src, start, src.length - start);
offset = src.length;
} else {
builder.append(this.handler.handleToken(expression.toString()));
offset = end + this.closeToken.length();
}
}
start = text.indexOf(this.openToken, offset);
} while(start > -1);
if (offset < src.length) {
builder.append(src, offset, src.length - offset);
}
return builder.toString();
}
} else {
return "";
}
}



