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,configurationIt 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.
can also be configured by package dimension if necessary.

#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