background
In the development process, we often do not directly interact with the database through mysql-Client. Instead, we will use some third-party ORM-like toolkits to simplify the operation process. Mybatis is a data access layer tool with high agility.Copy the code
structure
Version: 3.5.3
Some other features are left out, such as reflection, transactions, plugins, languages, etc.
Expose interfaces
Most of the time we will not use MyBatis without Spring, but today we focus on the analysis of the flow, so run it alone, to run MyBatis alone requires configuration information, Mapper interface, Mapper XML mapping example below.
Use cases
public static void main(String[] args) throws IOException {
// Obtain configuration resources
InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml");
/ / build sqlsessionfactory
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
SqlSessionFactory build = sqlSessionFactoryBuilder.build(resourceAsStream);
// Call the database after retrieving the session session
SqlSession sqlSession = build.openSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<UserInfo> list = mapper.list();
System.out.println(JSON.toJSONString(list));
}
Copy the code
mybatis-config.xml
<! DOCTYPEconfiguration PUBLIC "- / / mybatis.org//DTD Config / 3.0 / EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="JDBC: mysql: / / 127.0.0.1:3306 / db_user? useSSL=false"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="UserMapper.xml"/>
</mappers>
</configuration>
Copy the code
UserMapper.xml
<! DOCTYPEmapper PUBLIC "- / / mybatis.org//DTD Mapper / 3.0 / EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.poizon.study.sb.mybatis.UserMapper">
<select id="list" resultType="com.poizon.study.sb.mybatis.UserInfo">
SELECT * from user_info;
</select>
</mapper>
Copy the code
UserMapper.java , UserInfo.java
public interface UserMapper {
@Select("SELECT * from user_info;" )
List<UserInfo> list(a);
}
@Data
public class UserInfo {
private Long id;
private String username;
private Date createAt;
}
Copy the code
Case analysis
The main objects we are dealing with in this case areSqlSessionFactory
,SqlSession
, the main methods aresqlSessionFactoryBuilder.build()
,build.openSession()
,sqlSession.getMapper()
Before the analysis, we will load the configuration file during the framework startup process according to the experience of source code analysis. The function that does not build() is to load the configuration. The following is a configuration map (including mybatis-config and mapper.xml).The correspondence is clear,configuration
It acts as a configuration center, and functions as a container in the project. The following figure shows the execution flow.
The application layer uses SqlSessionFactory to get SqlSession sessions, which execute specific calls through the Executor Executor. The call layer and return layer use StatementHandler to wrap parameters and returns.
Configuration file Parsing
Mybatis parsing configuration file is DOM parsing, (generally there are four parsing methods DOM, SAX, DOM4j, jDOM), if the file is large many professional frameworks use DOM4j, because DOM parsing will load the whole document, if the document is too large to cause memory overflow problem, We go in from the entry SqlSessionFactoryBuilder#build().
public SqlSessionFactory build( inputStream, environment, properties) {
XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
return build(parser.parse());// Continue clicking
}
org.apache.ibatis.builder.xml.XMLConfigBuilder#parseConfiguration
private void parseConfiguration(XNode root) {
/ /...
typeAliasesElement(root.evalNode("typeAliases"));
mapperElement(root.evalNode("mappers"));
}
Copy the code
There are a lot of child tags parsed here, so let’s find two representative ones for analysis. TypeAliases, whose semantics refer to typeAliases, We can in a configuration file such configuration < typeAliases > < typeAlias type = “com. Poizon. Study. Sb. Mybatis. The UserInfo” alias = “myUserType” / > < / typeAliases >, UserInfo can be abbreviated to myUserType. ParameterType is often used in Mapper resultType and parameterType.
#org.apache.ibatis.builder.xml.XMLConfigBuilder#typeAliasesElement
private void typeAliasesElement(XNode parent) {
for (XNode child : parent.getChildren()) {
if ("package".equals(child.getName())) {
/ /...
} else {
String alias = child.getStringAttribute("alias");
String type = child.getStringAttribute("type"); Class<? > clazz = Resources.classForName(type); typeAliasRegistry.registerAlias(alias, clazz); } } } #org.apache.ibatis.type.TypeAliasRegistry#registerAlias()public void registerAlias(String alias, Class
value) {
String key = alias.toLowerCase(Locale.ENGLISH);
typeAliases.put(key, value);
}
Copy the code
The aliases are stored in the Map of The TypeAliasRegistry. Check out this class, which contains built-in aliases for many of the underlying data types, such as String => string. class and date=> date.class. GetTypeAliases () is used to return a list of aliases, but the map returned is not writable.
publicMap<String, Class<? >> getTypeAliases() {return Collections.unmodifiableMap(typeAliases);
}
Copy the code