å建项ç®
为äºçæ¸ æ¥MyBatisçæ´ä¸ªåå§åè¿ç¨ï¼å å建ä¸ä¸ªç®åçJava项ç®ï¼ç®å½ç»æå¦ä¸å¾æ示ï¼
以ä¸ä»£ç åæ代ç çæå¨çæ
Studentå®ä½ç±»
package com.softtool.mybatis.dao;
import java.io.Serializable;
public class Student implements Serializable {
private Integer id;
private String name;
private Integer age;
private String sex;
private static final long serialVersionUID = 1L;
public Student(Integer id, String name, Integer age, String sex) {
this.id = id;
this.name = name;
this.age = age;
this.sex = sex;
}
public Student() {
super();
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
@Override
public String toString() {
return "Student [id=" + id + ", name=" + name + ", age=" + age + ", sex=" + sex + "]";
}
}
StudentMapper ç±»
package com.softtool.mybatis.dao;
public interface StudentMapper {
int deleteByPrimaryKey(Integer id);
int insert(Student record);
int insertSelective(Student record);
Student selectByPrimaryKey(Integer id);
int updateByPrimaryKeySelective(Student record);
int updateByPrimaryKey(Student record);
}
é ç½®æ件xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.softtool.mybatis.dao.StudentMapper">
<resultMap id="BaseResultMap" type="com.softtool.mybatis.dao.Student">
<constructor>
<idArg column="id" javaType="java.lang.Integer" jdbcType="INTEGER" />
<arg column="name" javaType="java.lang.String" jdbcType="VARCHAR" />
<arg column="age" javaType="java.lang.Integer" jdbcType="INTEGER" />
<arg column="sex" javaType="java.lang.String" jdbcType="VARCHAR" />
</constructor>
</resultMap>
<sql id="Base_Column_List">
id, name, age, sex
</sql>
<select id="selectByPrimaryKey" parameterType="java.lang.Integer" resultMap="BaseResultMap">
select
<include refid="Base_Column_List" />
from student
where id = #{id,jdbcType=INTEGER}
</select>
<delete id="deleteByPrimaryKey" parameterType="java.lang.Integer">
delete from student
where id = #{id,jdbcType=INTEGER}
</delete>
<insert id="insert" parameterType="com.softtool.mybatis.dao.Student">
insert into student (id, name, age,
sex)
values (#{id,jdbcType=INTEGER}, #{name,jdbcType=VARCHAR}, #{age,jdbcType=INTEGER},
#{sex,jdbcType=VARCHAR})
</insert>
<insert id="insertSelective" parameterType="com.softtool.mybatis.dao.Student">
insert into student
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="id != null">
id,
</if>
<if test="name != null">
name,
</if>
<if test="age != null">
age,
</if>
<if test="sex != null">
sex,
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="id != null">
#{id,jdbcType=INTEGER},
</if>
<if test="name != null">
#{name,jdbcType=VARCHAR},
</if>
<if test="age != null">
#{age,jdbcType=INTEGER},
</if>
<if test="sex != null">
#{sex,jdbcType=VARCHAR},
</if>
</trim>
</insert>
<update id="updateByPrimaryKeySelective" parameterType="com.softtool.mybatis.dao.Student">
update student
<set>
<if test="name != null">
name = #{name,jdbcType=VARCHAR},
</if>
<if test="age != null">
age = #{age,jdbcType=INTEGER},
</if>
<if test="sex != null">
sex = #{sex,jdbcType=VARCHAR},
</if>
</set>
where id = #{id,jdbcType=INTEGER}
</update>
<update id="updateByPrimaryKey" parameterType="com.softtool.mybatis.dao.Student">
update student
set name = #{name,jdbcType=VARCHAR},
age = #{age,jdbcType=INTEGER},
sex = #{sex,jdbcType=VARCHAR}
where id = #{id,jdbcType=INTEGER}
</update>
</mapper>
mybatis.xml MyBatisçé ç½®æ件
<?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>
<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://localhost:3306/test"/>
<property name="username" value="root"/>
<property name="password" value=""/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="com/softtool/mybatis/dao/StudentMapper.xml"/>
</mappers>
</configuration>
pom.xml
项ç®æ¯maven项ç®ï¼é ç½®çpomå¦ä¸
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>test002</groupId>
<artifactId>test002</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.2.8</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.5</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.5</version>
</dependency>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>2.2.2</version>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-core</artifactId>
<version>1.3.5</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.38</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
</resources>
</build>
</project>
Main 主å½æ°
package com.softtool.mybatis;
import com.softtool.mybatis.dao.Student;
import com.softtool.mybatis.dao.StudentMapper;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.reflection.Reflector;
import org.apache.ibatis.reflection.invoker.Invoker;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.IOException;
import java.io.Reader;
import java.lang.reflect.Constructor;
/**
* Hello world!
*
*/
public class App
{
public static void main( String[] args ) throws IOException
{
Reader resourceAsReader = Resources.getResourceAsReader("mybatis.xml");
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(resourceAsReader);
SqlSession session = sqlSessionFactory.openSession();
StudentMapper mapper = session.getMapper(StudentMapper.class);
Student student = mapper.selectByPrimaryKey(1);
}
}
å建çsql
-- ----------------------------
-- Table structure for `student`
-- ----------------------------
DROP TABLE IF EXISTS `student`;
CREATE TABLE `student` (
`name` varchar(255) NOT NULL COMMENT 'å§å',
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'ç¼å·',
`age` int(11) DEFAULT NULL COMMENT 'å¹´é¾',
`sex` varchar(255) DEFAULT NULL COMMENT 'æ§å«',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=101 DEFAULT CHARSET=latin1;
-- ----------------------------
-- Records of student
-- ----------------------------
INSERT INTO `student` VALUES ('ss', '1', '1', 'mm');
INSERT INTO `student` VALUES ('ddd', '2', '2', 'women');
INSERT INTO `student` VALUES ('name1', '3', '2', 'nan');
INSERT INTO `student` VALUES ('222', '4', '31', 'man');
è¿è¡ç»æ
Student [id=1, name=ss, age=1, sex=mm]
MyBatisåå§åè¿ç¨
è·åé ç½®æ件
å½ç³»ç»åå§åæ¶ï¼é¦å ä¼è¯»åé ç½®æ件ï¼
Reader resourceAsReader = Resources.getResourceAsReader("mybatis.xml");
å建SqlSessionFactoryBuilder对象
ä»SqlSessionFactoryBuilderçååä¸å¯ä»¥çåºï¼SqlSessionFactoryBuilderæ¯ç¨æ¥å建SqlSessionFactory对象çã æ¥çä¸ä¸SqlSessionFactoryBuilderæºç ï¼ï¼SqlSessionFactoryBuilderä¸åªæä¸äºéè½½çbuildå½æ°ï¼è¿äºbuildå½æ°çå ¥åé½æ¯MyBatisé ç½®æ件çè¾å ¥æµï¼è¿åå¼é½æ¯SqlSessionFactoryï¼ç±æ¤å¯è§ï¼SqlSessionFactoryBuilderçä½ç¨å¾çº¯ç²¹ï¼å°±æ¯ç¨æ¥éè¿é ç½®æ件å建SqlSessionFactory对象çã
SqlSessionFactory å建è¿ç¨
ä¸é¢å ·ä½æ¥çä¸ä¸ï¼buildå½æ°æ¯å¦ä½å建SqlSessionFactory对象çã
public SqlSessionFactory build(Reader reader, String environment, Properties properties) {
try {
XMLConfigBuilder parser = new XMLConfigBuilder(reader, environment, properties);
return build(parser.parse());
} catch (Exception e) {
throw ExceptionFactory.wrapException("Error building SqlSession.", e);
} finally {
ErrorContext.instance().reset();
try {
reader.close();
} catch (IOException e) {
// Intentionally ignore. Prefer previous error.
}
}
}
æé XMLConfigBuilder对象
buildå½æ°é¦å ä¼æé ä¸ä¸ªXMLConfigBuilder对象ï¼ä»ååä¸å¤§è´å¯ä»¥çå°ï¼è¯¥å¯¹è±¡æ¯ç¨æ¥è§£æXMLé ç½®æ件çãä¸é¢æ¥çä¸ä¸XMLConfigBuilderçä½ç³»ç»æã
- XMLxxxBuilderæ¯ç¨æ¥è§£æXMLé ç½®æ件çï¼ä¸åç±»åXMLxxxBuilderç¨æ¥è§£æMyBatisé ç½®æ件çä¸åé¨ä½ãæ¯å¦ï¼XMLConfigBuilderç¨æ¥è§£æMyBatisçé ç½®æ件ï¼XMLMapperBuilderç¨æ¥è§£æMyBatisä¸çæ å°æ件ï¼å¦ä¸ææå°çProductMapper.xmlï¼ï¼XMLStatementBuilderç¨æ¥è§£ææ å°æ件ä¸çSQLè¯å¥ã
- è¿äºXMLxxxBuilderé½æä¸ä¸ªå ±åçç¶ç±»ââBaseBuilderãè¿ä¸ªç¶ç±»ç»´æ¤äºä¸ä¸ªå ¨å±çConfiguration对象ï¼MyBatisçé ç½®æ件解æå就以Configuration对象çå½¢å¼åå¨ã
- å½å建XMLConfigBuilder对象æ¶ï¼å°±ä¼åå§åConfiguration对象ï¼å¹¶ä¸å¨åå§åConfiguration对象çæ¶åï¼ä¸äºå«åä¼è¢«æ³¨åå°ConfigurationçtypeAliasRegistry容å¨ä¸ã
private XMLConfigBuilder(XPathParser parser, String environment, Properties props) {
super(new Configuration());
ErrorContext.instance().resource("SQL Mapper Configuration");
this.configuration.setVariables(props);
this.parsed = false;
this.environment = environment;
this.parser = parser;
}
public Configuration() {
typeAliasRegistry.registerAlias("JDBC", JdbcTransactionFactory.class);
typeAliasRegistry.registerAlias("MANAGED", ManagedTransactionFactory.class);
typeAliasRegistry.registerAlias("JNDI", JndiDataSourceFactory.class);
typeAliasRegistry.registerAlias("POOLED", PooledDataSourceFactory.class);
typeAliasRegistry.registerAlias("UNPOOLED", UnpooledDataSourceFactory.class);
typeAliasRegistry.registerAlias("PERPETUAL", PerpetualCache.class);
typeAliasRegistry.registerAlias("FIFO", FifoCache.class);
typeAliasRegistry.registerAlias("LRU", LruCache.class);
typeAliasRegistry.registerAlias("SOFT", SoftCache.class);
typeAliasRegistry.registerAlias("WEAK", WeakCache.class);
typeAliasRegistry.registerAlias("DB_VENDOR", VendorDatabaseIdProvider.class);
typeAliasRegistry.registerAlias("XML", XMLLanguageDriver.class);
typeAliasRegistry.registerAlias("RAW", RawLanguageDriver.class);
typeAliasRegistry.registerAlias("SLF4J", Slf4jImpl.class);
typeAliasRegistry.registerAlias("COMMONS_LOGGING", JakartaCommonsLoggingImpl.class);
typeAliasRegistry.registerAlias("LOG4J", Log4jImpl.class);
typeAliasRegistry.registerAlias("LOG4J2", Log4j2Impl.class);
typeAliasRegistry.registerAlias("JDK_LOGGING", Jdk14LoggingImpl.class);
typeAliasRegistry.registerAlias("STDOUT_LOGGING", StdOutImpl.class);
typeAliasRegistry.registerAlias("NO_LOGGING", NoLoggingImpl.class);
typeAliasRegistry.registerAlias("CGLIB", CglibProxyFactory.class);
typeAliasRegistry.registerAlias("JAVASSIST", JavassistProxyFactory.class);
languageRegistry.setDefaultDriverClass(XMLLanguageDriver.class);
languageRegistry.register(RawLanguageDriver.class);
}
解æé ç½®æ件
å½æäºXMLConfigBuilder对象ä¹åï¼æ¥ä¸æ¥å°±å¯ä»¥ç¨å®æ¥è§£æé ç½®æ件äº
private void parseConfiguration(XNode root) {
try {
propertiesElement(root.evalNode("properties")); //issue #117 read properties first
typeAliasesElement(root.evalNode("typeAliases"));
pluginElement(root.evalNode("plugins"));
objectFactoryElement(root.evalNode("objectFactory"));
objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));
settingsElement(root.evalNode("settings"));
environmentsElement(root.evalNode("environments")); // read it after objectFactory and objectWrapperFactory issue #631
databaseIdProviderElement(root.evalNode("databaseIdProvider"));
typeHandlerElement(root.evalNode("typeHandlers"));
mapperElement(root.evalNode("mappers"));
} catch (Exception e) {
throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e);
}
}
ä»ä¸è¿°ä»£ç ä¸å¯ä»¥çå°ï¼XMLConfigBuilderä¼ä¾æ¬¡è§£æé ç½®æ件ä¸ç<properties>ã< settings >ã< environments>ã< typeAliases >ã< plugins >ã< mappers >çå±æ§ãä¸é¢ä»ç»ä¸å 个éè¦å±æ§ç解æè¿ç¨ã
èç¹ç解æè¿ç¨
èç¹ï¼
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/test"/>
<property name="username" value="root"/>
<property name="password" value=""/>
- èç¹ç解æè¿ç¨ï¼
private void propertiesElement(XNode context) throws Exception {
if (context != null) {
Properties defaults = context.getChildrenAsProperties();
String resource = context.getStringAttribute("resource");
String url = context.getStringAttribute("url");
if (resource != null && url != null) {
throw new BuilderException("The properties element cannot specify both a URL and a resource based property file reference. Please specify one or the other.");
}
if (resource != null) {
defaults.putAll(Resources.getResourceAsProperties(resource));
} else if (url != null) {
defaults.putAll(Resources.getUrlAsProperties(url));
}
Properties vars = configuration.getVariables();
if (vars != null) {
defaults.putAll(vars);
}
parser.setVariables(defaults);
configuration.setVariables(defaults);
}
}
- é¦å 读å<resources>èç¹ä¸çææ<resource>èç¹ï¼å¹¶å°æ¯ä¸ªèç¹çnameåvalueå±æ§åå ¥Propertiesä¸ã
- ç¶å读å<resources>èç¹ä¸çresourceãurlå±æ§ï¼å¹¶è·åæå®é ç½®æ件ä¸çnameåvalueï¼ä¹åå ¥Propertiesä¸ãï¼PSï¼ç±æ¤å¯ç¥ï¼å¦æresourceèç¹ä¸å®ä¹çå±æ§åpropertiesæ件ä¸çå±æ§éåï¼é£ä¹propertiesæ件ä¸çå±æ§å¼ä¼è¦çresourceèç¹ä¸å®ä¹çå±æ§å¼ãï¼
- æç»ï¼æºå¸¦ææå±æ§çProperties对象ä¼è¢«åå¨å¨Configuration对象ä¸ã
settingsèç¹ç解æè¿ç¨
settings èç¹ç解æè¿ç¨ï¼ <settings>å±æ§ç解æè¿ç¨å <properties>å±æ§ç解æè¿ç¨æ为类似ï¼è¿éä¸åèµè¿°ãæç»ï¼ææçsettingå±æ§é½è¢«åå¨å¨Configuration对象ä¸ã
<settings>
<setting name="cacheEnabled" value="true"/>
<setting name="lazyLoadingEnabled" value="true"/>
<setting name="multipleResultSetsEnabled" value="true"/>
</settings>
mappersèç¹ç解æè¿ç¨
<mappers>èç¹çå®ä¹æ¹å¼æå¦ä¸åç§ï¼ æ¹å¼1ï¼
<mappers>
<package name="org.mybatis.builder"/>
</mappers>
æ¹å¼2ï¼
<mappers>
<mapper resource="org/mybatis/builder/AuthorMapper.xml"/>
</mappers>
æ¹å¼3ï¼
<mappers>
<mapper url="file:///var/mappers/AuthorMapper.xml"/>
</mappers>
æ¹å¼4ï¼
<mappers>
<mapper class="org.mybatis.builder.AuthorMapper"/>
</mappers>
<mappers>èç¹ç解æè¿ç¨å¦ä¸ï¼
private void mapperElement(XNode parent) throws Exception {
if (parent != null) {
for (XNode child : parent.getChildren()) {
if ("package".equals(child.getName())) {
String mapperPackage = child.getStringAttribute("name");
configuration.addMappers(mapperPackage);
} else {
String resource = child.getStringAttribute("resource");
String url = child.getStringAttribute("url");
String mapperClass = child.getStringAttribute("class");
if (resource != null && url == null && mapperClass == null) {
ErrorContext.instance().resource(resource);
InputStream inputStream = Resources.getResourceAsStream(resource);
XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, resource, configuration.getSqlFragments());
mapperParser.parse();
} else if (resource == null && url != null && mapperClass == null) {
ErrorContext.instance().resource(url);
InputStream inputStream = Resources.getUrlAsStream(url);
XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, url, configuration.getSqlFragments());
mapperParser.parse();
} else if (resource == null && url == null && mapperClass != null) {
Class<?> mapperInterface = Resources.classForName(mapperClass);
configuration.addMapper(mapperInterface);
} else {
throw new BuilderException("A mapper element may only specify a url, resource or class, but not more than one.");
}
}
}
}
}
MyBatisä¼éå<mappers>ä¸ææçåèç¹ï¼å¦æå½åéåå°çèç¹æ¯<package>ï¼åMyBatisä¼å°è¯¥å ä¸çææMapper Class注åå°configurationçmapperRegistry容å¨ä¸ã å¦æå½åèç¹ä¸º<mapper>ï¼åä¼ä¾æ¬¡è·åresourceãurlãclasså±æ§ï¼è§£ææ å°æ件ï¼å¹¶å°æ å°æ件对åºçMapper Class注åå°configurationçmapperRegistry容å¨ä¸ã
å ¶ä¸ï¼<mapper>èç¹ç解æè¿ç¨å¦ä¸ï¼
XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, resource, configuration.getSqlFragments());
mapperParser.parse()
å¨è§£æåï¼é¦å éè¦å建XMLMapperBuilderï¼å建è¿ç¨å¦ä¸ï¼
private XMLMapperBuilder(XPathParser parser, Configuration configuration, String resource, Map<String, XNode> sqlFragments) {
// å°configurationèµç»BaseBuilder
super(configuration);
// å建MapperBuilderAssistant对象ï¼è¯¥å¯¹è±¡ä¸ºMapperBuilderçåå©è
ï¼
this.builderAssistant = new MapperBuilderAssistant(configuration, resource);
this.parser = parser;
this.sqlFragments = sqlFragments;
this.resource = resource;
}
é¦å ä¼åå§åç¶ç±»BaseBuilderï¼å¹¶å°configurationèµç»BaseBuilderï¼ ç¶åå建MapperBuilderAssistant对象ï¼è¯¥å¯¹è±¡ä¸ºXMLMapperBuilderçåå©è ï¼ç¨æ¥åå©XMLMapperBuilderå®æä¸äºè§£ææ å°æ件çå¨ä½ã
å½æäºXMLMapperBuilderåï¼ä¾¿å¯è¿å ¥è§£æ<mapper>çè¿ç¨
public void parse() {
// è¥å½åçMapper.xmlå°æªè¢«è§£æï¼åå¼å§è§£æ
// PSï¼è¥<mappers>èç¹ä¸æç¸åç<mapper>èç¹ï¼é£ä¹å°±æ éå次解æäº
if (!configuration.isResourceLoaded(resource)) {
// 解æ<mapper>èç¹
configurationElement(parser.evalNode("/mapper"));
// å°è¯¥Mapper.xmlæ·»å è³configurationçLoadedResource容å¨ä¸ï¼ä¸åæ éå解æ
configuration.addLoadedResource(resource);
// å°è¯¥Mapper.xml对åºçMapper Class注åè¿configurationçmapperRegistry容å¨ä¸
bindMapperForNamespace();
}
parsePendingResultMaps();
parsePendingCacheRefs();
parsePendingStatements();
}
private void configurationElement(XNode context) {
try {
// è·å<mapper>èç¹ä¸çnamespaceå±æ§ï¼è¯¥å±æ§å¿
é¡»åå¨ï¼è¡¨ç¤ºå½åæ å°æ件对åºçMapper Classæ¯è°
String namespace = context.getStringAttribute("namespace");
if (namespace == null || namespace.equals("")) {
throw new BuilderException("Mapper's namespace cannot be empty");
}
// å°namespaceå±æ§å¼èµç»builderAssistant
builderAssistant.setCurrentNamespace(namespace);
// 解æ<cache-ref>èç¹
cacheRefElement(context.evalNode("cache-ref"));
// 解æ<cache>èç¹
cacheElement(context.evalNode("cache"));
// 解æ<parameterMap>èç¹
parameterMapElement(context.evalNodes("/mapper/parameterMap"));
// 解æ<resultMap>èç¹
resultMapElements(context.evalNodes("/mapper/resultMap"));
// 解æ<sql>èç¹
sqlElement(context.evalNodes("/mapper/sql"));
// 解æsqlè¯å¥
buildStatementFromContext(context.evalNodes("select|insert|update|delete"));
} catch (Exception e) {
throw new BuilderException("Error parsing Mapper XML. Cause: " + e, e);
}
}
resultMapElementså½æ°
该å½æ°ç¨äºè§£ææ å°æ件ä¸ææç<resultMap>èç¹ï¼è¿äºèç¹ä¼è¢«è§£ææResultMap对象ï¼åå¨å¨Configuration对象çresultMaps容å¨ä¸ã
<resultMap>èç¹å®ä¹å¦ä¸ï¼
<resultMap id="BaseResultMap" type="com.softtool.mybatis.dao.Student">
<constructor>
<idArg column="id" javaType="java.lang.Integer" jdbcType="INTEGER" />
<arg column="name" javaType="java.lang.String" jdbcType="VARCHAR" />
<arg column="age" javaType="java.lang.Integer" jdbcType="INTEGER" />
<arg column="sex" javaType="java.lang.String" jdbcType="VARCHAR" />
</constructor>
</resultMap>
<resultMap>èç¹ç解æè¿ç¨ï¼
private ResultMap resultMapElement(XNode resultMapNode, List<ResultMapping> additionalResultMappings) throws Exception {
ErrorContext.instance().activity("processing " + resultMapNode.getValueBasedIdentifier());
String id = resultMapNode.getStringAttribute("id",
resultMapNode.getValueBasedIdentifier());
String type = resultMapNode.getStringAttribute("type",
resultMapNode.getStringAttribute("ofType",
resultMapNode.getStringAttribute("resultType",
resultMapNode.getStringAttribute("javaType"))));
String extend = resultMapNode.getStringAttribute("extends");
Boolean autoMapping = resultMapNode.getBooleanAttribute("autoMapping");
Class<?> typeClass = resolveClass(type);
Discriminator discriminator = null;
List<ResultMapping> resultMappings = new ArrayList<ResultMapping>();
resultMappings.addAll(additionalResultMappings);
List<XNode> resultChildren = resultMapNode.getChildren();
for (XNode resultChild : resultChildren) {
if ("constructor".equals(resultChild.getName())) {
processConstructorElement(resultChild, typeClass, resultMappings);
} else if ("discriminator".equals(resultChild.getName())) {
discriminator = processDiscriminatorElement(resultChild, typeClass, resultMappings);
} else {
ArrayList<ResultFlag> flags = new ArrayList<ResultFlag>();
if ("id".equals(resultChild.getName())) {
flags.add(ResultFlag.ID);
}
resultMappings.add(buildResultMappingFromContext(resultChild, typeClass, flags));
}
}
ResultMapResolver resultMapResolver = new ResultMapResolver(builderAssistant, id, typeClass, extend, discriminator, resultMappings, autoMapping);
try {
return resultMapResolver.resolve();
} catch (IncompleteElementException e) {
configuration.addIncompleteResultMap(resultMapResolver);
throw e;
}
}
ResultMapResolverè¿ä¸ªç±»å¾çº¯ç²¹ï¼æä¸ä» æä¸ä¸ªå½æ°resolveï¼ç¨äºæé ResultMap对象ï¼å¹¶å°å ¶åå ¥Configuration对象çresultMaps容å¨ä¸ï¼èè¿ä¸ªè¿ç¨æ¯åå©äºMapperBuilderAssistant.addResultMapå®æçã
sqlElementå½æ° 该å½æ°ç¨äºè§£ææ å°æ件ä¸ææç<sql>èç¹ï¼å¹¶å°è¿äºèç¹åå¨å¨å½åæ å°æ件æ对åºçXMLMapperBuilder对象çsqlFragments容å¨ä¸ï¼ä¾è§£æsqlè¯å¥æ¶ä½¿ç¨ã- buildStatementFromContextå½æ° 该å½æ°ä¼å°æ å°æ件ä¸çsqlè¯å¥è§£ææMappedStatement对象ï¼å¹¶åå¨configurationçmappedStatementsã
转载äº:https://my.oschina.net/u/4006362/blog/2252784