一、成员变量
首先我们来看下Configuration的一些成员变量
1、简单参数
public class Configuration {
protected Environment environment;
protected boolean safeRowBoundsEnabled;
protected boolean safeResultHandlerEnabled = true;
protected boolean mapUnderscoreToCamelCase;
protected boolean aggressiveLazyLoading;
protected boolean multipleResultSetsEnabled = true;
protected boolean useGeneratedKeys;
protected boolean useColumnLabel = true;
protected boolean cacheEnabled = true;
protected boolean callSettersOnNulls;
protected boolean useActualParamName = true;
......
这些节点是我们可以在mybatis的配置文件配置,然后mybatis就会将这些信息读取到这个Configuration中来,我们们主要梳理下一些重要的属性。
2、defaultStatementTimeout
protected Integer defaultStatementTimeout;
这个就是设置Statement在进行查询连接的时候的默认超时时间
3、defaultFetchSize [setting name=“defaultFetchSize” value=“100”]
protected Integer defaultFetchSize;
这个就是用来设置fetchSize的值的,这个对于数据库来说,就是它不会将你能查询出来的一次全部返还回来,而是一次返回defaultFetchSize设置的值,当这个一直往后移完了,其再将后面下一批数据再返回,这样就能避免OOM的情况。
4、defaultResultSetType
protected ResultSetType defaultResultSetType;
这个参数就是用来设置再ResultSet遍历获取结果的时候类型的滚动情况
public enum ResultSetType {
DEFAULT(-1),
FORWARD_ONLY(ResultSet.TYPE_FORWARD_ONLY),
SCROLL_INSENSITIVE(ResultSet.TYPE_SCROLL_INSENSITIVE),
SCROLL_SENSITIVE(ResultSet.TYPE_SCROLL_SENSITIVE);
这里的FORWARD_ONLY表示只能往前、SCROLL_INSENSITIVE能左右,但其对数据库的修改不敏感、SCROLL_SENSITIVE对数据库的修改是敏感的。
5、defaultExecutorType
protected ExecutorType defaultExecutorType = ExecutorType.SIMPLE;
public enum ExecutorType {
SIMPLE, REUSE, BATCH
}
这个是mybatis的执行器类型,可以看到其有三种:SIMPLE是简单的执行器、REUSE是可复用的执行器(指定是其会将Statement缓存起来重复利用,而不是直接关闭它)、BATCH这个是批处理的执行器。
6、autoMappingBehavior
protected AutoMappingBehavior autoMappingBehavior = AutoMappingBehavior.PARTIAL;
其总共有3种类型:
public enum AutoMappingBehavior {
NONE,
PARTIAL,
FULL
}
NONO表示不进行自动映射,PARTIAL表示中对没有嵌套的属性进行自动映射,FULL表示其他的或者嵌套的都进行映射。
它这里要表示的其实是:
public class User {
private Integer id;
private String name;
private Long phone; // phone number of Long type
private List<Pet> pets;
insert into users (id, name, phone, phone_number) values(1, 'User1', '+86 12345678901', 12345678901);
<select id="getUserWithPhoneNumber" resultMap="resultWithPhoneNumber">
select * from users where id = #{id}
</select>
<resultMap type="org.apache.ibatis.submitted.automapping.User" id="resultWithPhoneNumber">
<result property="phone" column="phone_number"/>
</resultMap>
<select id="getUser" resultMap="result">
select id, name from users where id = #{id}
</select>
<resultMap type="org.apache.ibatis.submitted.automapping.User" id="result">
</resultMap>
例如这个设置类型为PARTIAL(默认),用getUser进行查询,其在resultMap没有写内容,同时由于"Long phone"与数据看中的"phone"类型不同其是字符,所以不会进行匹配,这个时候用getUserWithPhoneNumber其result有设置对应的映射,所以能查询出来。对于pets这个嵌套,就算是用sql查询出来了对应的关系,其也不会设置对应,所以这个时候需要设置FULL,当需要注意这个是全局设置,但其实还是可以设置sql语句级别:
private boolean shouldApplyAutomaticMappings(ResultMap resultMap, boolean isNested) {
if (resultMap.getAutoMapping() != null) {
return resultMap.getAutoMapping();
} else {
if (isNested) {
return AutoMappingBehavior.FULL == configuration.getAutoMappingBehavior();
} else {
return AutoMappingBehavior.NONE != configuration.getAutoMappingBehavior();
}
}
}
可以看到这里首先是看autoMapping属性:
<resultMap type="org.apache.ibatis.submitted.automapping.User" id="resultWithPhoneNumber" autoMapping="true">
<result property="phone" column="phone_number"/>
</resultMap>
7、variables
protected Properties variables = new Properties();
这个在mybatis文件中设置读取的properties的信息,例如
<properties>
<property name="driver" value="xxx" />
<property name="url" value="xxx" />
<property name="username" value="xxx" />
<property name="password" value="xxx" />
</properties>
8、objectFactory
protected ObjectFactory objectFactory = new DefaultObjectFactory();
public interface ObjectFactory {
void setProperties(Properties properties);
<T> T create(Class<T> type);
<T> T create(Class<T> type, List<Class<?>> constructorArgTypes, List<Object> constructorArgs);
<T> boolean isCollection(Class<T> type);
}
这个是用来产生对象的工厂的,我们可以看其接口,主要有两个方法,一个是主键创建,另一个是通过构造方法&参数来创建对象。
9、objectWrapperFactory
protected ObjectWrapperFactory objectWrapperFactory = new DefaultObjectWrapperFactory();
这个类是用来产生包装对象的,这个工厂是用来生产ObjectWrapper的。
public interface ObjectWrapper {
......
String[] getGetterNames();
String[] getSetterNames();
Class<?> getSetterType(String name);
Class<?> getGetterType(String name);
boolean hasSetter(String name);
boolean hasGetter(String name);
......
}
例如用来判断有没有这个属性的get|set方法。
10、mapperRegistry
protected MapperRegistry mapperRegistry = new MapperRegistry(this);
public class MapperRegistry {
private Configuration config;
private final Map<Class<?>, MapperProxyFactory<?>> knownMappers = new HashMap<Class<?>, MapperProxyFactory<?>>();
......
这个类就是用来存放Mapper接口类以及这个接口类所对应的代理工厂。
11、interceptorChain
protected final InterceptorChain interceptorChain = new InterceptorChain();
public class InterceptorChain {
private final List<Interceptor> interceptors = new ArrayList<Interceptor>();
这个类就是用来存放Mybatis的Interceptor的。
12、typeHandlerRegistry
protected final TypeHandlerRegistry typeHandlerRegistry = new TypeHandlerRegistry();
这个我们上一篇也有提到,是用来做类型处理的,将对应表示类型的字符,来获取对应字符表示的类型或类型处理器。
13、typeAliasRegistry
protected final TypeAliasRegistry typeAliasRegistry = new TypeAliasRegistry();
这个是用来处理别名的,例如直接设置类的别名,或者自动扫描包名,使用的时候只需要些对应的类名称就可以了:
<typeAliases>
<typeAlias type="org.apache.ibatis.submitted.cache.Person" alias="Person" />
</typeAliases>
<typeAliases>
<package name="org.apache.ibatis.submitted.permissions" />
</typeAliases>
14、languageRegistry
protected final LanguageDriverRegistry languageRegistry = new LanguageDriverRegistry();
这个在上一篇也有梳理过,其主要是用来驱动对sql脚本的解析的。
15、mappedStatements
protected final Map<String, MappedStatement> mappedStatements = new StrictMap<MappedStatement>("Mapped Statements collection");
这个Map是很重要的,其就是对应Mapper接口的方法为key,对应的MappedStatement包含这个接口方法正常执行sql所需要的一些数据。
不过我们可以看到这些key有些带了包名有些没有带包名,之后我们梳理流程的时候看为什么会这样。
但我们看MappedStatement的对应属性。
1)、resource
这个表示资源所在位置。
2)、id
这个就是唯一表示,可以看到前面的key没有包名,这个也是带包名的,同时通过这两个key我们也能大致知道为什么mybatis为什么是不支持方法同名的(方法对应的参数类型不同),因为一是方法名确认,而没有参数表示的。
3)、statementType
public enum StatementType {
STATEMENT, PREPARED, CALLABLE
}
这个就是表示一个sql的Statement类型:STATEMENT就是直接表示的简单的Statement、PREPARED表示的是PreparedStatement、CALLABLE表示的与存储过程调用相关的,我们就先忽略,这里的区别就是获取不同的Statement处理器:
public RoutingStatementHandler(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
switch (ms.getStatementType()) {
case STATEMENT:
delegate = new SimpleStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql);
break;
case PREPARED:
delegate = new PreparedStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql);
break;
case CALLABLE:
delegate = new CallableStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql);
break;
default:
throw new ExecutorException("Unknown statement type: " + ms.getStatementType());
}
}
4)、resultSetType
private ResultSetType resultSetType;
结果集类型,这个在上面有对应介绍
5)、sqlSource
private SqlSource sqlSource;
这个在上篇文章有过对应介绍,表示处理与Sql节本相关的内容的。
6)、parameterMap
private ParameterMap parameterMap;
<parameterMap id="selectAuthor" type="org.apache.ibatis.domain.blog.Author">
<parameter property="id" resultMap="id"/>
</parameterMap>
这个表示参数的map映射
7)、resultMaps
private List<ResultMap> resultMaps;
id="personMap2" type="Person">
<id property="id" column="id"/>
<result property="firstName" column="firstName"/>
这个就是表示对应的返回映射,这里可以看到其是一个数组,但一般是只有一个值。这里看注释之所以是数组是因为一些存储过程可能会有两个返回。
8)、sqlCommandType
public enum SqlCommandType {
UNKNOWN, INSERT, UPDATE, DELETE, SELECT;
}
这个就是对应的哪种操作。
9)、keyColumns&keyProperties&keyGenerator
private String[] keyColumns;
private String[] keyProperties;
private KeyGenerator keyGenerator;
这个是用于主键策略的,我们跳过。
10)、hasNestedResultMaps
private boolean hasNestedResultMaps;
这个表示是否有嵌套ResultMap。
11)、databaseId
private String databaseId;
这个表示这条sql使用的数据库Id。
<databaseIdProvider type="DB_VENDOR">
<property name="SQL Server" value="sqlserver"/>
<property name="DB2" value="db2"/>
<property name="Oracle" value="oracle" />
<property name="HSQL Database Engine" value="hsql" />
</databaseIdProvider>
<select id="select1" databaseId="hsql" resultType="string" parameterType="int">
select name from hsql where
id=#{value}
</select>
12)、resultSets
<select id="getNamesAndItemsLinked" statementType="CALLABLE" resultSets="names,items" resultMap="nameResultLinked">
{call sptest.getnamesanditems()}
</select>
create procedure sptest.getnamesanditems()
modifies sql data
dynamic result sets 2
BEGIN ATOMIC
declare cur1 cursor for select * from sptest.names;
declare cur2 cursor for select * from sptest.items;
open cur1;
open cur2;
END
go
这个是存储过程可能有两个返回结果集。现在还没有在工作中用到这种用法,不是很了解,先不具体分析了。
13)、resultMaps
protected final Map<String, ResultMap> resultMaps = new StrictMap<ResultMap>("Result Maps collection");
这个是整个加载的结果映射集
14)、parameterMaps
protected final Map<String, ParameterMap> parameterMaps = new StrictMap<ParameterMap>("Parameter Maps collection");
与上面类似,这个是总的参数映射集。
15)、sqlFragments
protected final Map<String, XNode> sqlFragments = new StrictMap<XNode>("XML fragments parsed from previous mappers");
这个是存放sql片段节点的。
16)、incompleteStatements&incompleteCacheRefs&incompleteResultMaps&incompleteMethods
protected final Collection<XMLStatementBuilder> incompleteStatements = new LinkedList<XMLStatementBuilder>();
protected final Collection<CacheRefResolver> incompleteCacheRefs = new LinkedList<CacheRefResolver>();
protected final Collection<ResultMapResolver> incompleteResultMaps = new LinkedList<ResultMapResolver>();
protected final Collection<MethodResolver> incompleteMethods = new LinkedList<MethodResolver>();
这些是用来存放一些例如你的sql标记写错了,这个就是用来收集的。
} catch (IncompleteElementException e) {
configuration.addIncompleteStatement(statementParser);
}
例如这几个字段的使用一般是放在catch中记录的,