Código fuente de Mybatis
声明:此过程仅记录本人DEBUG过程,如有错误请指出!
JDBC
Ejemplo:
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 }
Obtenga el conductor aquí
Seguimiento del código fuente de Mybatis
Toma el método de construcción como entrada
Ingrese el método de análisis
Ingrese el método parseConfiguration
Mybatis.xml correspondiente
<?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&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>
Ingrese el método mapperElement
Supongamos que configuramos pachage en xml
Supongamos que configuramos el recurso de mapeador en xml
Ingrese el método configurationElement
Ingrese el método parseStatementNode, aquí para obtener información sobre el nodo, incluidos algunos atributos
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);
}
Finalmente construya un MappedStatement
Ingrese el método 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;
}
Aquí podemos ver que el objeto MappedStatement encapsulado final se agrega a una colección
Esta es una colección de mapeadores
Todo el mundo sabe que si las claves de la colección Map son iguales se sobrescribirá, pero si configuramos los métodos en el mismo mapeador en varios minutos se reportará un error, el motivo es el método put, que aquí se reescribe.
Analizar y ejecutar SQL
Ingrese getMapper
Hereda la interfaz InvocationHandler
Así que echemos un vistazo a su método de invocación.
Ingrese este método de ejecución
Procesamiento según sql
Yo uso seleccionar aquí, primero determine el tipo de valor de retorno, aquí hay una colección de lista, por lo que hay múltiples
La configuración es la siguiente
Dado que estamos usando # {} como SQL estático, ¿el SQL aquí todavía usa marcadores de posición? , Posteriormente asignado por set
Establecer el valor aquí