導航:首頁 > 源碼編譯 > mybatis標簽源碼解析

mybatis標簽源碼解析

發布時間:2022-09-03 06:25:26

A. 怎麼沒有mybatis源碼解析相關的文檔

我們還記得是這樣配置sqlSessionFactory的:
[java] view plain
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="configLocation" value="classpath:configuration.xml"></property>
<property name="mapperLocations" value="classpath:com/xxx/mybatis/mapper/*.xml"/>
<property name="typeAliasesPackage" value="com.tiantian.mybatis.model" />
</bean>
這里配置了一個mapperLocations屬性,它是一個表達式,sqlSessionFactory會根據這個表達式讀取包com.xxx.myts.mapper下面的所有xml格式文件,那麼具體是怎麼根據這個屬性來讀取配置文件的呢?
答案就在SqlSessionFactoryBean類中的buildSqlSessionFactory方法中:

[java] view plain
if (!isEmpty(this.mapperLocations)) {
for (Resource mapperLocation : this.mapperLocations) {
if (mapperLocation == null) {
continue;
}

try {
XMLMapperBuilder xmlMapperBuilder = new XMLMapperBuilder(mapperLocation.getInputStream(),
configuration, mapperLocation.toString(), configuration.getSqlFragments());
xmlMapperBuilder.parse();
} catch (Exception e) {
throw new NestedIOException("Failed to parse mapping resource: '" + mapperLocation + "'", e);
} finally {
ErrorContext.instance().reset();
}

if (logger.isDebugEnabled()) {
logger.debug("Parsed mapper file: '" + mapperLocation + "'");
}
}
}

mybatis使用XMLMapperBuilder類的實例來解析mapper配置文件。
[java] view plain
public XMLMapperBuilder(Reader reader, Configuration configuration, String resource, Map<String, XNode> sqlFragments) {
this(new XPathParser(reader, true, configuration.getVariables(), new XMLMapperEntityResolver()),
configuration, resource, sqlFragments);
}

[java] view plain
private XMLMapperBuilder(XPathParser parser, Configuration configuration, String resource, Map<String, XNode> sqlFragments) {
super(configuration);
this.builderAssistant = new MapperBuilderAssistant(configuration, resource);
this.parser = parser;
this.sqlFragments = sqlFragments;
this.resource = resource;
}
接著系統調用xmlMapperBuilder的parse方法解析mapper。

[java] view plain
public void parse() {
//如果configuration對象還沒載入xml配置文件(避免重復載入,實際上是確認是否解析了mapper節點的屬性及內容,
//為解析它的子節點如cache、sql、select、resultMap、parameterMap等做准備),
//則從輸入流中解析mapper節點,然後再將resource的狀態置為已載入
if (!configuration.isResourceLoaded(resource)) {
configurationElement(parser.evalNode("/mapper"));
configuration.addLoadedResource(resource);
bindMapperForNamespace();
}
//解析在configurationElement函數中處理resultMap時其extends屬性指向的父對象還沒被處理的<resultMap>節點
parsePendingResultMaps();
//解析在configurationElement函數中處理cache-ref時其指向的對象不存在的<cache>節點(如果cache-ref先於其指向的cache節點載入就會出現這種情況)
parsePendingChacheRefs();
//同上,如果cache沒載入的話處理statement時也會拋出異常
parsePendingStatements();
}

mybatis解析mapper的xml文件的過程已經很明顯了,接下來我們看看它是怎麼解析mapper的:
[java] view plain
private void configurationElement(XNode context) {
try {
//獲取mapper節點的namespace屬性
String namespace = context.getStringAttribute("namespace");
if (namespace.equals("")) {
throw new BuilderException("Mapper's namespace cannot be empty");
}
//設置當前namespace
builderAssistant.setCurrentNamespace(namespace);
//解析mapper的<cache-ref>節點
cacheRefElement(context.evalNode("cache-ref"));
//解析mapper的<cache>節點
cacheElement(context.evalNode("cache"));
//解析mapper的<parameterMap>節點
parameterMapElement(context.evalNodes("/mapper/parameterMap"));
//解析mapper的<resultMap>節點
resultMapElements(context.evalNodes("/mapper/resultMap"));
//解析mapper的<sql>節點
sqlElement(context.evalNodes("/mapper/sql"));
//使用XMLStatementBuilder的對象解析mapper的<select>、<insert>、<update>、<delete>節點,
//myts會使用MappedStatement.Builder類build一個MappedStatement對象,
//所以myts中一個sql對應一個MappedStatement
buildStatementFromContext(context.evalNodes("select|insert|update|delete"));
} catch (Exception e) {
throw new BuilderException("Error parsing Mapper XML. Cause: " + e, e);
}
}
configurationElement函數幾乎解析了mapper節點下所有子節點,至此myts解析了mapper中的所有節點,並將其加入到了Configuration對象中提供給sqlSessionFactory對象隨時使用。這里我們需要補充講一下myts是怎麼使用XMLStatementBuilder類的對象的parseStatementNode函數借用MapperBuilderAssistant類對象builderAssistant的addMappedStatement解析MappedStatement並將其關聯到Configuration類對象的:

[java] view plain
public void parseStatementNode() {
//ID屬性
String id = context.getStringAttribute("id");
//databaseId屬性
String databaseId = context.getStringAttribute("databaseId");

if (!databaseIdMatchesCurrent(id, databaseId, this.requiredDatabaseId)) {
return;
}
//fetchSize屬性
Integer fetchSize = context.getIntAttribute("fetchSize");
//timeout屬性
Integer timeout = context.getIntAttribute("timeout");
//parameterMap屬性
String parameterMap = context.getStringAttribute("parameterMap");
//parameterType屬性
String parameterType = context.getStringAttribute("parameterType");
Class<?> parameterTypeClass = resolveClass(parameterType);
//resultMap屬性
String resultMap = context.getStringAttribute("resultMap");
//resultType屬性
String resultType = context.getStringAttribute("resultType");
//lang屬性
String lang = context.getStringAttribute("lang");
LanguageDriver langDriver = getLanguageDriver(lang);

Class<?> resultTypeClass = resolveClass(resultType);
//resultSetType屬性
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));
//是否是<select>節點
boolean isSelect = sqlCommandType == SqlCommandType.SELECT;
//flushCache屬性
boolean flushCache = context.getBooleanAttribute("flushCache", !isSelect);
//useCache屬性
boolean useCache = context.getBooleanAttribute("useCache", isSelect);
//resultOrdered屬性
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);
//resultSets屬性
String resultSets = context.getStringAttribute("resultSets");
//keyProperty屬性
String keyProperty = context.getStringAttribute("keyProperty");
//keyColumn屬性
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 {
//useGeneratedKeys屬性
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);
}
由以上代碼可以看出myts使用XPath解析mapper的配置文件後將其中的resultMap、parameterMap、cache、statement等節點使用關聯的builder創建並將得到的對象關聯到configuration對象中,而這個configuration對象可以從sqlSession中獲取的,這就解釋了我們在使用sqlSession對資料庫進行操作時myts怎麼獲取到mapper並執行其中的sql語句的問題。

B. 初看Mybatis 源碼 SQL是怎麼執行的

其實Mybatis的整個執行過程,理解起來分為如下幾個過程: 1. 載入配置文件 2. 解析配置文件,從配置文件中解析出來 datasource、mapper文件、事務配置等等。將配置信息保存在對象內 3. 調用相關語句,執行sql。在執行的方法中分別完成JDBC的一系...

C. mybatis 是sax還是dom解析的

看了mybatis源碼,負責任告訴你,mybatis使用的是SAX解析XML的

D. 初看Mybatis 源碼 SQL是怎麼執行的

其實Mybatis的整個執行過程,理解起來分為如下幾個過程:
1. 載入配置文件
2. 解析配置文件,從配置文件中解析出來 datasource、mapper文件、事務配置等等。將配置信息保存在對象內
3. 調用相關語句,執行sql。在執行的方法中分別完成JDBC的一系列操作。

E. MyBatis­Plus快速入門源碼筆記共享,拿走吧你

為什麼要學習它呢?

答:MyBatisPlus可以節省我們大量工作時間,所有的CRUD代碼它都可以自動化完成!

優點:
1. 易於上手和掌握。
2. sql寫在xml里,便於統一管理和優化。
3. 解除sql與程序代碼的耦合。
4. 提供映射標簽,支持對象與資料庫的orm欄位關系映射
5. 提供對象關系映射標簽,支持對象關系組建維護
6. 提供xml標簽,支持編寫動態sql。

MyBatis Plus(簡稱 MP)是一個 MyBatis的增強工具,在 MyBatis 的基礎上只做增強不做改變,為簡化開發、提高效率而生。

就像 魂斗羅 中的 1P、2P,基友搭配,效率翻倍。

特性:

無侵入 :只做增強不做改變,引入它不會對現有工程產生影響,如絲般順滑。

損耗小 :啟動即會自動注入基本 CURD,性能基本無損耗,直接面向對象操作 強大的 CRUD 操作 :內置通用 Mapper、通用 Service,僅僅通過少量配置即可實現單表大部分 CRUD 操作,更有強大的條件構造器,滿足各類使用需求 支持 Lambda 形式調用 :通過 Lambda 表達式,方便地編寫各類查詢條件,無需再擔心欄位寫錯。

支持組件自動生成 :支持多達 4 種主鍵策略(內含分布式唯一 ID 生成器 Sequence),可自由配置,完美解決主鍵問題。

支持 ActiveRecord 模式 :支持 ActiveRecord 形式調用,實體類只需繼承 Model 類即可進行強大的 CRUD 操作。

支持自定義全局通用操作 :支持全局通用方法注入( Write once, use anywhere )。

內置代碼生成器 :採用代碼或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、 Controller 層代碼,支持模板引擎,更有超多自定義配置等您來使用 內置分頁插件 :基於 MyBatis 物理分頁,開發者無需關心具體操作,配置好插件之後,寫分頁等同於普通 List查詢。

分頁插件支持多種資料庫 :支持 MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、Postgre、SQLServer 等多種資料庫。

內置性能分析插件 :可輸出 Sql 語句以及其執行時間,建議開發測試時啟用該功能,能快速揪出慢查詢。

內置全局攔截插件 :提供全表 delete 、 update 操作智能分析阻斷,也可自定義攔截規則,預防誤操作。

1.1 、引入mybatis-plus相關maven依賴


引入mybatis-plus在spring boot中的場景啟動器


ps:切記不可再在pom.xml文件中引入mybatis與mybatis-spring的maven依賴,這一點,mybatis-plus的官方文檔中已經說明的很清楚了.

1.2、創建數據表

(1)SQL語句



(2) 數據表結構

1.3、 創建java bean

根據數據表新建相關實體類

1 package com.example.demo.pojo



1.4、 配置application.proprties

數據源使用druid



ps:在進行crud實驗之前,簡單對mybatis與mybatis-plus做一個簡單的對比

2.1、mybatis與mybatis-plus實現方式對比

(1)提出問題: 假設我們已存在一張 tbl_employee 表,且已有對應的實體類 Employee,實現 tbl_employee 表的 CRUD操作我們需要做什麼呢?

(2)實現方式: 基於 Mybatis 需要編寫 EmployeeMapper 介面,並手動編寫 CRUD 方法 提供 EmployeeMapper.xml 映射文件,並手動編寫每個方法對應的 SQL 語句. 基於 Mybatis-plus 只需要創建 EmployeeMapper 介面, 並繼承BaseMapper 介面.這就是使用 mybatis-plus 需要完成的所有操作,甚至不需要創建 SQL 映射文件。

2.2、BaseMapper介面介紹

(1)如何理解核心介面BaseMapper?

在使用Mybatis-Plus時,核心操作類是BaseMapper介面,其最終也是利用的Mybatis介面編程的實現機制,其默認提供了一系列的增刪改查的基礎方法,並且開發人員對於這些基礎操作不需要寫SQL進行處理操作(Mybatis提供的機制就是需要開發人員在mapper.xml中提供sql語句),那樣我們可以猜測肯定是Mybatis-Plus完成了BaseMapper介面提供的方法的SQL語句的生成操作。

(2)BaseMapper介面為我們定義了哪些方法?

BaseMapper介面源碼:





(3) mybatis-plus中常用的註解 1


由於我們的數據表名於實體類的類名不一致,並且實體類於數據表還存在欄位名不對應的情況,因此我們需要引入mybatis-plus的註解.



編寫EmployeeMapper介面繼承BaseMapper介面



准備考試環境:



(1)插入



(2)修改



控制台列印出的sql語句

如果我們不設置實體類的email與gender屬性,結果是怎樣的呢?



控制台sql語句:

顯然,mybatis-plus為我們做了非空判斷,空值的話,默認不更新對應的欄位.想一想,這是不是類似於mybatis中的動態sql呢?

這種處理效果又會帶來什麼好處呢?

(3)查詢



selectById方法



selectBatchIds方法



ps:發現該方法底層使用的竟然是sql的in關鍵字

selectByMap方法



(4)刪除



3、不得不提的條件構造器---Wrapper

3.1.wrapper及其子類介紹

(1)Wrapper :條件構造抽象類,最頂端父類,抽象類中提供3個方法以及其他方法.

F. Mybatis裡面的TypeHandler是做什麼的

無論是 MyBatis 在預處理語句(PreparedStatement)中設置一個參數時,還是從結果集中取出一個值時,都會用類型處理器將獲取的值以合適的方式轉換成 Java 類型。Mybatis默認為我們實現了許多TypeHandler, 當我們沒有配置指定TypeHandler時,Mybatis會根據參數或者返回結果的不同,默認為我們選擇合適的TypeHandler處理。
那麼,Mybatis為我們實現了哪些TypeHandler呢? 我們怎麼自定義實現一個TypeHandler ? 這些都會在接下來的mybatis的源碼中看到。
在看源碼之前,還是像之前一樣,先看看怎麼配置吧?
配置TypeHandler:
<configuration>
<typeHandlers>
<!--
當配置package的時候,mybatis會去配置的package掃描TypeHandler
<package name="com.dy.demo"/>
-->

<!-- handler屬性直接配置我們要指定的TypeHandler -->
<typeHandler handler=""/>

<!-- javaType 配置java類型,例如String, 如果配上javaType, 那麼指定的typeHandler就只作用於指定的類型 -->
<typeHandler javaType="" handler=""/>

<!-- jdbcType 配置資料庫基本數據類型,例如varchar, 如果配上jdbcType, 那麼指定的typeHandler就只作用於指定的類型 -->
<typeHandler jdbcType="" handler=""/>

<!-- 也可兩者都配置 -->
<typeHandler javaType="" jdbcType="" handler=""/>

</typeHandlers>

......

</configuration>

上面簡單介紹了一下TypeHandler, 下面就看看mybatis中TypeHandler的源碼了。
=========================================================我是源碼分割線==========================================================
老規矩,先從對xml的解析講起:
/**
* 解析typeHandlers節點
*/
private void typeHandlerElement(XNode parent) throws Exception {
if (parent != null) {
for (XNode child : parent.getChildren()) {
//子節點為package時,獲取其name屬性的值,然後自動掃描package下的自定義typeHandler
if ("package".equals(child.getName())) {
String typeHandlerPackage = child.getStringAttribute("name");
typeHandlerRegistry.register(typeHandlerPackage);
} else {
//子節點為typeHandler時, 可以指定javaType屬性, 也可以指定jdbcType, 也可兩者都指定
//javaType 是指定java類型
//jdbcType 是指定jdbc類型(資料庫類型: 如varchar)
String javaTypeName = child.getStringAttribute("javaType");
String jdbcTypeName = child.getStringAttribute("jdbcType");
//handler就是我們配置的typeHandler
String handlerTypeName = child.getStringAttribute("handler");
//resolveClass方法就是我們上篇文章所講的TypeAliasRegistry裡面處理別名的方法
Class<?> javaTypeClass = resolveClass(javaTypeName);
//JdbcType是一個枚舉類型,resolveJdbcType方法是在獲取枚舉類型的值
JdbcType jdbcType = resolveJdbcType(jdbcTypeName);
Class<?> typeHandlerClass = resolveClass(handlerTypeName);
//注冊typeHandler, typeHandler通過TypeHandlerRegistry這個類管理
if (javaTypeClass != null) {
if (jdbcType == null) {
typeHandlerRegistry.register(javaTypeClass, typeHandlerClass);
} else {
typeHandlerRegistry.register(javaTypeClass, jdbcType, typeHandlerClass);
}
} else {
typeHandlerRegistry.register(typeHandlerClass);
}
}
}
}
}

接下來看看TypeHandler的管理注冊類:
TypeHandlerRegistry:
/**
* typeHandler注冊管理類
*/
public final class TypeHandlerRegistry {

//源碼一上來,二話不說,幾個大大的HashMap就出現,這不又跟上次講的typeAliases的注冊類似么

//基本數據類型與其包裝類
private static final Map<Class<?>, Class<?>> reversePrimitiveMap = new HashMap<Class<?>, Class<?>>() {
private static final long serialVersionUID = 1L;
{
put(Byte.class, byte.class);
put(Short.class, short.class);
put(Integer.class, int.class);
put(Long.class, long.class);
put(Float.class, float.class);
put(Double.class, double.class);
put(Boolean.class, boolean.class);
put(Character.class, char.class);
}
};

//這幾個MAP不用說就知道存的是什麼東西吧,命名的好處
private final Map<JdbcType, TypeHandler<?>> JDBC_TYPE_HANDLER_MAP = new EnumMap<JdbcType, TypeHandler<?>>(JdbcType.class);
private final Map<Type, Map<JdbcType, TypeHandler<?>>> TYPE_HANDLER_MAP = new HashMap<Type, Map<JdbcType, TypeHandler<?>>>();
private final TypeHandler<Object> UNKNOWN_TYPE_HANDLER = new UnknownTypeHandler(this);
private final Map<Class<?>, TypeHandler<?>> ALL_TYPE_HANDLERS_MAP = new HashMap<Class<?>, TypeHandler<?>>();

//就像上篇文章講的typeAliases一樣,mybatis也默認給我們注冊了不少的typeHandler
//具體如下
public TypeHandlerRegistry() {
register(Boolean.class, new BooleanTypeHandler());
register(boolean.class, new BooleanTypeHandler());
register(JdbcType.BOOLEAN, new BooleanTypeHandler());
register(JdbcType.BIT, new BooleanTypeHandler());

register(Byte.class, new ByteTypeHandler());
register(byte.class, new ByteTypeHandler());
register(JdbcType.TINYINT, new ByteTypeHandler());

register(Short.class, new ShortTypeHandler());
register(short.class, new ShortTypeHandler());
register(JdbcType.SMALLINT, new ShortTypeHandler());

register(Integer.class, new IntegerTypeHandler());
register(int.class, new IntegerTypeHandler());
register(JdbcType.INTEGER, new IntegerTypeHandler());

register(Long.class, new LongTypeHandler());
register(long.class, new LongTypeHandler());

register(Float.class, new FloatTypeHandler());
register(float.class, new FloatTypeHandler());
register(JdbcType.FLOAT, new FloatTypeHandler());

register(Double.class, new DoubleTypeHandler());
register(double.class, new DoubleTypeHandler());
register(JdbcType.DOUBLE, new DoubleTypeHandler());

register(String.class, new StringTypeHandler());
register(String.class, JdbcType.CHAR, new StringTypeHandler());
register(String.class, JdbcType.CLOB, new ClobTypeHandler());
register(String.class, JdbcType.VARCHAR, new StringTypeHandler());
register(String.class, JdbcType.LONGVARCHAR, new ClobTypeHandler());
register(String.class, JdbcType.NVARCHAR, new NStringTypeHandler());
register(String.class, JdbcType.NCHAR, new NStringTypeHandler());
register(String.class, JdbcType.NCLOB, new NClobTypeHandler());
register(JdbcType.CHAR, new StringTypeHandler());
register(JdbcType.VARCHAR, new StringTypeHandler());
register(JdbcType.CLOB, new ClobTypeHandler());
register(JdbcType.LONGVARCHAR, new ClobTypeHandler());
register(JdbcType.NVARCHAR, new NStringTypeHandler());
register(JdbcType.NCHAR, new NStringTypeHandler());
register(JdbcType.NCLOB, new NClobTypeHandler());

register(Object.class, JdbcType.ARRAY, new ArrayTypeHandler());
register(JdbcType.ARRAY, new ArrayTypeHandler());

register(BigInteger.class, new BigIntegerTypeHandler());
register(JdbcType.BIGINT, new LongTypeHandler());

register(BigDecimal.class, new BigDecimalTypeHandler());
register(JdbcType.REAL, new BigDecimalTypeHandler());
register(JdbcType.DECIMAL, new BigDecimalTypeHandler());
register(JdbcType.NUMERIC, new BigDecimalTypeHandler());

register(Byte[].class, new ByteObjectArrayTypeHandler());
register(Byte[].class, JdbcType.BLOB, new ());
register(Byte[].class, JdbcType.LONGVARBINARY, new ());
register(byte[].class, new ByteArrayTypeHandler());
register(byte[].class, JdbcType.BLOB, new BlobTypeHandler());
register(byte[].class, JdbcType.LONGVARBINARY, new BlobTypeHandler());
register(JdbcType.LONGVARBINARY, new BlobTypeHandler());
register(JdbcType.BLOB, new BlobTypeHandler());

register(Object.class, UNKNOWN_TYPE_HANDLER);
register(Object.class, JdbcType.OTHER, UNKNOWN_TYPE_HANDLER);
register(JdbcType.OTHER, UNKNOWN_TYPE_HANDLER);

register(Date.class, new DateTypeHandler());
register(Date.class, JdbcType.DATE, new DateOnlyTypeHandler());
register(Date.class, JdbcType.TIME, new TimeOnlyTypeHandler());
register(JdbcType.TIMESTAMP, new DateTypeHandler());
register(JdbcType.DATE, new DateOnlyTypeHandler());
register(JdbcType.TIME, new TimeOnlyTypeHandler());

register(java.sql.Date.class, new SqlDateTypeHandler());
register(java.sql.Time.class, new SqlTimeTypeHandler());
register(java.sql.Timestamp.class, new SqlTimestampTypeHandler());

// issue #273
register(Character.class, new CharacterTypeHandler());
register(char.class, new CharacterTypeHandler());
}

public boolean hasTypeHandler(Class<?> javaType) {
return hasTypeHandler(javaType, null);
}

public boolean hasTypeHandler(TypeReference<?> javaTypeReference) {
return hasTypeHandler(javaTypeReference, null);
}

public boolean hasTypeHandler(Class<?> javaType, JdbcType jdbcType) {
return javaType != null && getTypeHandler((Type) javaType, jdbcType) != null;
}

public boolean hasTypeHandler(TypeReference<?> javaTypeReference, JdbcType jdbcType) {
return javaTypeReference != null && getTypeHandler(javaTypeReference, jdbcType) != null;
}

public TypeHandler<?> getMappingTypeHandler(Class<? extends TypeHandler<?>> handlerType) {
return ALL_TYPE_HANDLERS_MAP.get(handlerType);
}

public <T> TypeHandler<T> getTypeHandler(Class<T> type) {
return getTypeHandler((Type) type, null);
}

public <T> TypeHandler<T> getTypeHandler(TypeReference<T> javaTypeReference) {
return getTypeHandler(javaTypeReference, null);
}

public TypeHandler<?> getTypeHandler(JdbcType jdbcType) {
return JDBC_TYPE_HANDLER_MAP.get(jdbcType);
}

public <T> TypeHandler<T> getTypeHandler(Class<T> type, JdbcType jdbcType) {
return getTypeHandler((Type) type, jdbcType);
}

public <T> TypeHandler<T> getTypeHandler(TypeReference<T> javaTypeReference, JdbcType jdbcType) {
return getTypeHandler(javaTypeReference.getRawType(), jdbcType);
}

private <T> TypeHandler<T> getTypeHandler(Type type, JdbcType jdbcType) {
Map<JdbcType, TypeHandler<?>> jdbcHandlerMap = TYPE_HANDLER_MAP.get(type);
TypeHandler<?> handler = null;
if (jdbcHandlerMap != null) {
handler = jdbcHandlerMap.get(jdbcType);
if (handler == null) {
handler = jdbcHandlerMap.get(null);
}
}
if (handler == null && type != null && type instanceof Class && Enum.class.isAssignableFrom((Class<?>) type)) {
handler = new EnumTypeHandler((Class<?>) type);
}
@SuppressWarnings("unchecked")
// type drives generics here
TypeHandler<T> returned = (TypeHandler<T>) handler;
return returned;
}

public TypeHandler<Object> getUnknownTypeHandler() {
return UNKNOWN_TYPE_HANDLER;
}

public void register(JdbcType jdbcType, TypeHandler<?> handler) {
JDBC_TYPE_HANDLER_MAP.put(jdbcType, handler);
}

//
// REGISTER INSTANCE
//

G. mybatis工作原理及為什麼要用

一、mybatis的工作原理:

MyBatis 是支持普通 SQL查詢,存儲過程和高級映射的優秀持久層框架。MyBatis 消除了幾乎所有的JDBC代碼和參數的手工設置以及結果集的檢索。

MyBatis使用簡單的 XML或註解用於配置和原始映射,將介面和 Java 的POJOs(Plain Ordinary Java Objects,普通的 Java對象)映射成資料庫中的記錄。

每個MyBatis應用程序主要都是使用SqlSessionFactory實例的,一個SqlSessionFactory實例可以通過SqlSessionFactoryBuilder獲得。用xml文件構建SqlSessionFactory實例是非常簡單的事情。

推薦在這個配置中使用類路徑資源,但可以使用任何Reader實例,包括用文件路徑或file://開頭的url創建的實例。MyBatis有一個實用類----Resources,它有很多方法,可以方便地從類路徑及其它位置載入資源。

二、使用mybatis的原因:因為mybatis具有許多的優點,具體如下:

1、簡單易學:本身就很小且簡單。沒有任何第三方依賴,最簡單安裝只要兩個jar文件+配置幾個sql映射文件易於學習,易於使用,通過文檔和源代碼,可以比較完全的掌握它的設計思路和實現。

2、靈活:mybatis不會對應用程序或者資料庫的現有設計強加任何影響。 sql寫在xml里,便於統一管理和優化。通過sql語句可以滿足操作資料庫的所有需求。

3、解除sql與程序代碼的耦合:通過提供DAO層,將業務邏輯和數據訪問邏輯分離,使系統的設計更清晰,更易維護,更易單元測試。sql和代碼的分離,提高了可維護性。

4、提供映射標簽,支持對象與資料庫的orm欄位關系映射。

5、提供對象關系映射標簽,支持對象關系組建維護。

6、提供xml標簽,支持編寫動態sql。

(7)mybatis標簽源碼解析擴展閱讀:

mybatis的功能構架:

1、API介面層:提供給外部使用的介面API,開發人員通過這些本地API來操縱資料庫。介面層一接收到調用請求就會調用數據處理層來完成具體的數據處理。

2、數據處理層:負責具體的SQL查找、SQL解析、SQL執行和執行結果映射處理等。它主要的目的是根據調用的請求完成一次資料庫操作。

3、基礎支撐層:負責最基礎的功能支撐,包括連接管理、事務管理、配置載入和緩存處理,這些都是共用的東西,將他們抽取出來作為最基礎的組件。為上層的數據處理層提供最基礎的支撐。

H. 什麼是mybatis 為什麼要使用my batis

1、定義
MyBatis是一個支持普通SQL查詢,存儲過程和高級映射的優秀持久層框架。

2、使用原因
MyBatis消除了幾乎所有的JDBC代碼和參數的手工設置以及對結果集的檢索封裝。MyBatis可以使用簡單的XML或註解用於配置和原始映射,將介面和Java的POJO(Plain Old Java Objects,普通的Java對象)映射成資料庫中的記錄。

3、總體流程
(1)載入配置並初始化
觸發條件:載入配置文件
處理過程:將SQL的配置信息載入成為一個個MappedStatement對象(包括了傳入參數映射配置、執行的SQL語句、結果映射配置),存儲在內存中。
(2)接收調用請求
觸發條件:調用Mybatis提供的API
傳入參數:為SQL的ID和傳入參數對象
處理過程:將請求傳遞給下層的請求處理層進行處理。
(3)處理操作請求
觸發條件:API介面層傳遞請求過來
傳入參數:為SQL的ID和傳入參數對象
處理過程:
(A)根據SQL的ID查找對應的MappedStatement對象。
(B)根據傳入參數對象解析MappedStatement對象,得到最終要執行的SQL和執行傳入參數。
(C)獲取資料庫連接,根據得到的最終SQL語句和執行傳入參數到資料庫執行,並得到執行結果。
(D)根據MappedStatement對象中的結果映射配置對得到的執行結果進行轉換處理,並得到最終的處理結果。
(E)釋放連接資源。
(4)返回處理結果將最終的處理結果返回。

I. 什麼是mybatis

  1. MyBatis 是一個可以自定義SQL、存儲過程和高級映射的持久層框架。MyBatis 摒除了大部分的JDBC代碼、手工設置參數和結果集重獲。MyBatis 只使用簡單的XML 和註解來配置和映射基本數據類型、Map 介面和POJO 到資料庫記錄。相對Hibernate和Apache OJB等「一站式」ORM解決方案而言,Mybatis 是一種「半自動化」的ORM實現。

  2. 需要使用的Jar包:mybatis-3.0.2.jar(mybatis核心包)。mybatis-spring-1.0.0.jar(與Spring結合包)。

  3. MyBatis的前身是ibatis,但是在配置sql的語法上有明顯的區別,並且spring目前的版本封裝mybatis,至於mybatis-spring.jar文件也是mybatis團隊復雜開發的jar包,用於和spring整合。之前ibatis的源碼託管方是apache,而mybatis是google。

J. 怎麼學習mybatis框架的源碼

剛剛好我前段時間做了一個基於SpringMVC + Mybatis + Redis + Freemarker(JSP)的許可權控制Demo。地址看下面代碼:/** * 網路不讓輸入網址 * 地址為 */String url = "

閱讀全文

與mybatis標簽源碼解析相關的資料

熱點內容
卡爾曼濾波演算法書籍 瀏覽:769
安卓手機怎麼用愛思助手傳文件進蘋果手機上 瀏覽:844
安卓怎麼下載60秒生存 瀏覽:803
外向式文件夾 瀏覽:240
dospdf 瀏覽:431
怎麼修改騰訊雲伺服器ip 瀏覽:392
pdftoeps 瀏覽:496
為什麼鴻蒙那麼像安卓 瀏覽:736
安卓手機怎麼拍自媒體視頻 瀏覽:186
單片機各個中斷的初始化 瀏覽:724
python怎麼集合元素 瀏覽:481
python逐條解讀 瀏覽:833
基於單片機的濕度控制 瀏覽:499
ios如何使用安卓的帳號 瀏覽:883
程序員公園采訪 瀏覽:812
程序員實戰教程要多長時間 瀏覽:979
企業數據加密技巧 瀏覽:135
租雲伺服器開發 瀏覽:814
程序員告白媽媽不同意 瀏覽:337
攻城掠地怎麼查看伺服器 瀏覽:601