[소스 코드 분석] DEBUG Mybatis 소스 코드의 일부

Mybatis 소스 코드


声明:此过程仅记录本人DEBUG过程,如有错误请指出!


JDBC

예:

	public class JDBCTest {
    
    
 12     
 13     public static void jdbcDemoSelect(String driver,String url,String user,String password) throws Exception {
    
    
 14         
 15         //1.加载类驱动
 16         Class.forName(driver);
 17         Connection con = DriverManager.getConnection(url,user,password);
 18     
 19 //        if(!con.isClosed())
 20 //            System.out.println("succeeded connection to the database");
 21         
 22         //2.创建statement类对象,用来执行SQL语句
 23         Statement statement = con.createStatement();
 24         
 25         //SQL语句
 26         String sql = "select * from emp";    
 27         
 28         //3.ResultSet类,用来存放获取的结果集
 29         ResultSet set = statement.executeQuery(sql);
 30         
 31         String eid=null,ename=null,price=null;
 32         
 33         while(set.next()) {
    
    
 34             eid = set.getString("eid");
 35             ename = set.getString("ename");
 36             price = set.getString("price");
 37             
 38             System.out.println(eid+"\t"+ename+"\t"+price);
 39         }
 40         
 41     }

여기에서 드라이버 받기

여기에 사진 설명 삽입

Mybatis 소스 코드 후속 조치

빌드 방법을 입구로 사용

여기에 사진 설명 삽입

여기에 사진 설명 삽입

구문 분석 방법 입력
여기에 사진 설명 삽입

parseConfiguration 메소드를 입력하십시오.
여기에 사진 설명 삽입

해당 mybatis.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <settings>
        <setting name="logImpl" value="LOG4J"/>
    </settings>
    <!-- 别名 -->
    <typeAliases>
        <!-- <typeAlias type="com.test.pojo.People" alias="po" /> -->
        <package name="com.lmy.pojo" />
    </typeAliases>

    <environments default="default">
        <environment id="default">
            <transactionManager type="JDBC"></transactionManager>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/usermanager?autoReconnect=true&amp;useSSL=false"/>
                <property name="username" value="root"/>
                <property name="password" value="121891"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <!-- <mapper resource="com/test/mapper/StudentMapper.xml" />
        <mapper resource="com/test/mapper/TeacherMapper.xml" /> -->
        <!--<mapper class="com.test.mapper.TeacherMapper" />-->
        <package name="com.lmy.mapper"/>
    </mappers>

</configuration>


mapperElement 메소드 입력

여기에 사진 설명 삽입

xml에서 pachage를 구성한다고 가정합니다.
여기에 사진 설명 삽입

여기에 사진 설명 삽입

xml에서 mapper의 리소스를 구성한다고 가정합니다.

여기에 사진 설명 삽입

여기에 사진 설명 삽입

여기에 사진 설명 삽입

여기에 사진 설명 삽입

configurationElement 메소드 입력

여기에 사진 설명 삽입

여기에 사진 설명 삽입

여기에 사진 설명 삽입

parseStatementNode 메서드를 입력합니다. 여기에 일부 속성을 포함하여 노드에 대한 정보를 얻을 수 있습니다.

public void parseStatementNode() {
    
    
    String id = context.getStringAttribute("id");
    String databaseId = context.getStringAttribute("databaseId");

    if (!databaseIdMatchesCurrent(id, databaseId, this.requiredDatabaseId)) return;

    Integer fetchSize = context.getIntAttribute("fetchSize");
    Integer timeout = context.getIntAttribute("timeout");
    String parameterMap = context.getStringAttribute("parameterMap");
    String parameterType = context.getStringAttribute("parameterType");
    Class<?> parameterTypeClass = resolveClass(parameterType);
    String resultMap = context.getStringAttribute("resultMap");
    String resultType = context.getStringAttribute("resultType");
    String lang = context.getStringAttribute("lang");
    LanguageDriver langDriver = getLanguageDriver(lang);

    Class<?> resultTypeClass = resolveClass(resultType);
    String resultSetType = context.getStringAttribute("resultSetType");
    StatementType statementType = StatementType.valueOf(context.getStringAttribute("statementType", StatementType.PREPARED.toString()));
    ResultSetType resultSetTypeEnum = resolveResultSetType(resultSetType);

    String nodeName = context.getNode().getNodeName();
    SqlCommandType sqlCommandType = SqlCommandType.valueOf(nodeName.toUpperCase(Locale.ENGLISH));
    boolean isSelect = sqlCommandType == SqlCommandType.SELECT;
    boolean flushCache = context.getBooleanAttribute("flushCache", !isSelect);
    boolean useCache = context.getBooleanAttribute("useCache", isSelect);
    boolean resultOrdered = context.getBooleanAttribute("resultOrdered", false);

    // Include Fragments before parsing
    XMLIncludeTransformer includeParser = new XMLIncludeTransformer(configuration, builderAssistant);
    includeParser.applyIncludes(context.getNode());

    // Parse selectKey after includes and remove them.
    processSelectKeyNodes(id, parameterTypeClass, langDriver);
    
    // Parse the SQL (pre: <selectKey> and <include> were parsed and removed)
    SqlSource sqlSource = langDriver.createSqlSource(configuration, context, parameterTypeClass);
    String resultSets = context.getStringAttribute("resultSets");
    String keyProperty = context.getStringAttribute("keyProperty");
    String keyColumn = context.getStringAttribute("keyColumn");
    KeyGenerator keyGenerator;
    String keyStatementId = id + SelectKeyGenerator.SELECT_KEY_SUFFIX;
    keyStatementId = builderAssistant.applyCurrentNamespace(keyStatementId, true);
    if (configuration.hasKeyGenerator(keyStatementId)) {
    
    
      keyGenerator = configuration.getKeyGenerator(keyStatementId);
    } else {
    
    
      keyGenerator = context.getBooleanAttribute("useGeneratedKeys",
          configuration.isUseGeneratedKeys() && SqlCommandType.INSERT.equals(sqlCommandType))
          ? new Jdbc3KeyGenerator() : new NoKeyGenerator();
    }

    builderAssistant.addMappedStatement(id, sqlSource, statementType, sqlCommandType,
        fetchSize, timeout, parameterMap, parameterTypeClass, resultMap, resultTypeClass,
        resultSetTypeEnum, flushCache, useCache, resultOrdered, 
        keyGenerator, keyProperty, keyColumn, databaseId, langDriver, resultSets);
  }

마지막으로 MappedStatement 생성

여기에 사진 설명 삽입

addMappedStatement 메소드를 입력하십시오.

여기에 사진 설명 삽입

public MappedStatement addMappedStatement(
    String id,
    SqlSource sqlSource,
    StatementType statementType,
    SqlCommandType sqlCommandType,
    Integer fetchSize,
    Integer timeout,
    String parameterMap,
    Class<?> parameterType,
    String resultMap,
    Class<?> resultType,
    ResultSetType resultSetType,
    boolean flushCache,
    boolean useCache,
    boolean resultOrdered,
    KeyGenerator keyGenerator,
    String keyProperty,
    String keyColumn,
    String databaseId,
    LanguageDriver lang,
    String resultSets) {
  
  if (unresolvedCacheRef) throw new IncompleteElementException("Cache-ref not yet resolved");
  
  id = applyCurrentNamespace(id, false);
  boolean isSelect = sqlCommandType == SqlCommandType.SELECT;

  MappedStatement.Builder statementBuilder = new MappedStatement.Builder(configuration, id, sqlSource, sqlCommandType);
  statementBuilder.resource(resource);
  statementBuilder.fetchSize(fetchSize);
  statementBuilder.statementType(statementType);
  statementBuilder.keyGenerator(keyGenerator);
  statementBuilder.keyProperty(keyProperty);
  statementBuilder.keyColumn(keyColumn);
  statementBuilder.databaseId(databaseId);
  statementBuilder.lang(lang);
  statementBuilder.resultOrdered(resultOrdered);
  statementBuilder.resulSets(resultSets);
  setStatementTimeout(timeout, statementBuilder);

  setStatementParameterMap(parameterMap, parameterType, statementBuilder);
  setStatementResultMap(resultMap, resultType, resultSetType, statementBuilder);
  setStatementCache(isSelect, flushCache, useCache, currentCache, statementBuilder);

  MappedStatement statement = statementBuilder.build();
  configuration.addMappedStatement(statement);
  return statement;
}

여기에 사진 설명 삽입

여기에서 캡슐화 된 최종 MappedStatement 객체가 컬렉션에 추가 된 것을 볼 수 있습니다.

여기에 사진 설명 삽입

이것은 매퍼 컬렉션입니다

여기에 사진 설명 삽입

Map 컬렉션의 키가 같으면 덮어 쓰게된다는 것은 누구나 알고 있지만, 동일한 매퍼에서 몇 분 안에 메소드를 구성하면 오류가보고됩니다. 이유는 여기에서 다시 작성하는 put 메소드 때문입니다.

여기에 사진 설명 삽입

SQL 분석 및 실행

getMapper 입력

여기에 사진 설명 삽입

여기에 사진 설명 삽입

여기에 사진 설명 삽입

여기에 사진 설명 삽입

여기에 사진 설명 삽입

InvocationHandler 인터페이스를 상속합니다.

여기에 사진 설명 삽입

이제 invoke 메소드를 살펴 보겠습니다.
여기에 사진 설명 삽입

이 실행 방법 입력

여기에 사진 설명 삽입

SQL에 따른 처리

여기서 select를 사용하고 먼저 반환 값의 유형을 결정합니다. 여기에 목록 모음이 있으므로 여러

여기에 사진 설명 삽입

여기에 사진 설명 삽입

여기에 사진 설명 삽입

구성은 다음과 같습니다.

여기에 사진 설명 삽입

여기에 사진 설명 삽입

여기에 사진 설명 삽입

여기에 사진 설명 삽입

# {}을 정적 SQL로 사용하고 있기 때문에 여기서 SQL은 여전히 ​​자리 표시자를 사용합니까? , 나중에 세트로 지정

여기에 사진 설명 삽입

여기에 사진 설명 삽입
여기에 사진 설명 삽입

여기에 사진 설명 삽입

여기에 사진 설명 삽입

여기에 사진 설명 삽입

여기에 사진 설명 삽입

여기에 사진 설명 삽입

여기에 사진 설명 삽입

여기에 사진 설명 삽입

여기에 값 설정

추천

출처blog.csdn.net/qq_42380734/article/details/108281416