MyBatis 本是apache的一個開源項目iBatis, 2010年這個項目由apache software foundation 遷移到了google code,而且更名爲MyBatis 。2013年11月遷移到Github。html
MyBatis 是一款優秀的持久層框架,它支持定製化 SQL、存儲過程以及高級映射。MyBatis 避免了幾乎全部的 JDBC 代碼和手動設置參數以及獲取結果集。MyBatis 可使用簡單的 XML 或註解來配置和映射原生信息,將接口和 Java 的 POJOs(Plain Old Java Objects,普通的 Java對象)映射成數據庫中的記錄。java
優勢:mysql
缺點:
須要手動編寫SQL語句和映射規則,某些狀況下會加大工做量web
官網幫助文檔:http://www.mybatis.org/mybatis-3/zh/index.htmlsql
SqlSessionFactory能夠經過兩種方式進行建立,一種是java代碼生成,一種是讀取XML配置文件生成。通常你們都使用XML模式進行建立,由於修改時比較方便,方便往後的管理,其次看起來也比較直觀。數據庫
這是一個簡單mybatis的配置文件,只配置了數據庫。通常都是以mybatis-config.xml命名apache
<?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> <!--數據庫環境 --> <properties resource="jdbc.properties"/> <environments default="development"> <environment id="decelopment"> <transactionManager type="JDBC" /> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/mybatis_studydb"/> <property name="username" value="root"/> <property name="password" value=""/> </dataSource> </environment> </environments> </configuration>
有了數據庫環境,咱們就能夠簡單生成SqlSessionFactory了數組
// 配置文件放到了resources文件夾中 // 若是你放到了一個包中,你能夠這樣找到它 com/lzx/config/mybatis-config.xml String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource);//讀取配置文件 MySqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
// 配置數據庫 PooledDataSource dataSource = new PooledDataSource(); dataSource.setDriver("com.mysql.jdbc.Driver"); dataSource.setUrl("jdbc:mysql://localhost:3306/mybatis_studydb"); dataSource.setUsername("root"); dataSource.setPassword(""); // 關閉事務的自動提交 dataSource.setDefaultAutoCommit(false); // 採用Mybatis的JDBC的事務方式 TransactionFactory transactionFactory = new JdbcTransactionFactory(); Environment environment = new Environment("development", transactionFactory, dataSource); Configuration configuration = new Configuration(environment); // 加入映射器 configuration.addMapper(BlogMapper.class); // 建立SqlSessionFactory SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(configuration)
mybatis中SqlSession是它的核心接口,有兩個實現類:DefaultSqlSession和SqlSessionManager,其中DefaultSqlSession是在單線程中使用的,SqlSessionManager是在多線程中使用的。緩存
SqlSession共有一下三個做用:服務器
獲取Mapper接口
發送SQL給數據庫
控制數據庫事務
//這裏的sqlSessionFactory是上面SqlSessionFactory建立出來的· SqlSession session = sqlSessionFactory.openSession(); try { // do work sqlSessionFactory.commit(); } catch (Exception e){ sqlSessionFactory.rollback(); } finally { session.close(); }
映射器是MyBtis中最爲重要、最複雜的組件。能夠經過XML文件和註解的形式去實現。能夠用來配置如下內容:
這裏咱們暫時先了解一下它,由於它最爲重要,咱們之後會單獨去學習掌握。
映射器接口:
@Repository public interface BillingInfoDAO { BillingInfoEntity queryById(int id); }
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.lzx.dao.BillingInfoDAO"> <select id="queryById" resultType="com.lzx.entity.BillingInfoEntity"> select invoice_id,billing_address,billing_city,billing_state, billing_country,billing_postalcode from invoice where invoice_id=#{id} </select> </mapper>
註解實現映射器:
public interface BillingInfoDAO { //這裏不推薦使用,較爲複雜的sql語句不便於管理 @select(select invoice_id,billing_address,billing_city,billing_state, billing_country,billing_postalcode from invoice where invoice_id=#{id}) BillingInfoEntity queryById(int id); }
瞭解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> <properties /> <!--屬性--> <settings /> <!--設置--> <typeAliases /> <!--類型別名--> <typeHandlers /> <!--類型處理器--> <objectFactory /> <!--對象工廠--> <environments > <!--配置環境--> <environment > <!--環境配置--> <transactionManager ></transactionManager> <!--事務管理器--> <dataSource></dataSource> <!--數據源--> </environment> </environments> <databaseIdProvider /> <!--數據庫廠商--> <mappers /> <!--映射器--> </configuration>
接下來咱們開始掌握這些元素的使用,接下來的全部配置都是在configuration裏面完成的,注意這些元素的順序必定要按照上面的順序,不可隨意放置, MyBatis的配置文件通常以mybatis-config.xml來命名,放置到類的加載路徑下。
<!-- 經過porpert的子元素來進行數據庫鏈接的相關配置--> <properties> <property name="jdbc.driver" value="com.mysql.jdbc.Driver" /> <property name="jdbc.url" value="jdbc:mysql://localhost:3306/mybatis_studydb" /> <property name="jdbc.username" value="root" /> <property name="jdbc.password" value="123456" /> </properties> <environments default="development"> <environment id="decelopment"> <transactionManager type="JDBC" /> <dataSource type="POOLED"> <property name="driver" value="${jdbc.driver}"/> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> </dataSource> </environment> </environments>
爲了方便管理,咱們通常使用properties文件進行數據庫的鏈接配置。建立jdbc.properties文件,放置classpath路徑下。方便咱們配置數據庫。
jdbc.driver=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/mybatis_studydb jdbc.username=root jdbc.password=123456
接下來咱們就能夠把properties和它的子元素進行替換便可
<properties resource="jdbc.properties"/>
settings是 MyBatis 中極爲重要的調整設置,它們會改變 MyBatis 的運行時行爲。大部分狀況下保持默認值運行便可。
一個配置完整的 settings 元素的示例以下:
<settings> <setting name="cacheEnabled" value="true"/> <setting name="lazyLoadingEnabled" value="true"/> <setting name="multipleResultSetsEnabled" value="true"/> <setting name="useColumnLabel" value="true"/> <setting name="useGeneratedKeys" value="false"/> <setting name="autoMappingBehavior" value="PARTIAL"/> <setting name="autoMappingUnknownColumnBehavior" value="WARNING"/> <setting name="defaultExecutorType" value="SIMPLE"/> <setting name="defaultStatementTimeout" value="25"/> <setting name="defaultFetchSize" value="100"/> <setting name="safeRowBoundsEnabled" value="false"/> <setting name="mapUnderscoreToCamelCase" value="false"/> <setting name="localCacheScope" value="SESSION"/> <setting name="jdbcTypeForNull" value="OTHER"/> <setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString"/> </settings>
下面是settings配置項的詳細說明:
設置參數 | 描述 | 有效值 | 默認值 |
---|---|---|---|
cacheEnabled | 全局地開啓或關閉配置文件中的全部映射器已經配置的任何緩存。 | true|false | true |
lazyLoadingEnabled | 延遲加載的全局開關。當開啓時,全部關聯對象都會延遲加載。特定關聯關係中可經過設置fetchType屬性來覆蓋該項的開關狀態。 | true|false | false |
aggressiveLazyLoading | 當開啓時,任何方法的調用都會加載該對象的全部屬性。不然,每一個屬性會按需加載(參考lazyLoadTriggerMethods). | true|false | false(truein≤3.4.1) |
multipleResultSetsEnabled | 是否容許單一語句返回多結果集(須要兼容驅動)。 | true|false | true |
useColumnLabel | 使用列標籤代替列名。不一樣的驅動在這方面會有不一樣的表現,具體可參考相關驅動文檔或經過測試這兩種不一樣的模式來觀察所用驅動的結果。 | true|false | true |
useGeneratedKeys | 容許JDBC支持自動生成主鍵,須要驅動兼容。若是設置爲true則這個設置強制使用自動生成主鍵,儘管一些驅動不能兼容但仍可正常工做(好比Derby)。 | true|false | False |
autoMappingBehavior | 指定MyBatis應如何自動映射列到字段或屬性。NONE表示取消自動映射;PARTIAL只會自動映射沒有定義嵌套結果集映射的結果集。FULL會自動映射任意複雜的結果集(不管是否嵌套)。 | NONE,PARTIAL,FULL | PARTIAL |
autoMappingUnknownColumnBehavior | 指定發現自動映射目標未知列(或者未知屬性類型)的行爲。
|
NONE,WARNING,FAILING | NONE |
defaultExecutorType | 配置默認的執行器。SIMPLE就是普通的執行器;REUSE執行器會重用預處理語句(preparedstatements);BATCH執行器將重用語句並執行批量更新。 | SIMPLEREUSEBATCH | SIMPLE |
defaultStatementTimeout | 設置超時時間,它決定驅動等待數據庫響應的秒數。 | 任意正整數 | NotSet(null) |
defaultFetchSize | 爲驅動的結果集獲取數量(fetchSize)設置一個提示值。此參數只能夠在查詢設置中被覆蓋。 | 任意正整數 | NotSet(null) |
safeRowBoundsEnabled | 容許在嵌套語句中使用分頁(RowBounds)。若是容許使用則設置爲false。 | true|false | False |
safeResultHandlerEnabled | 容許在嵌套語句中使用分頁(ResultHandler)。若是容許使用則設置爲false。 | true|false | True |
mapUnderscoreToCamelCase | 是否開啓自動駝峯命名規則(camelcase)映射,即從經典數據庫列名A_COLUMN到經典Java屬性名aColumn的相似映射。 | true|false | False |
localCacheScope | MyBatis利用本地緩存機制(LocalCache)防止循環引用(circularreferences)和加速重複嵌套查詢。默認值爲SESSION,這種狀況下會緩存一個會話中執行的全部查詢。若設置值爲STATEMENT,本地會話僅用在語句執行上,對相同SqlSession的不一樣調用將不會共享數據。 | SESSION|STATEMENT | SESSION |
jdbcTypeForNull | 當沒有爲參數提供特定的JDBC類型時,爲空值指定JDBC類型。某些驅動須要指定列的JDBC類型,多數狀況直接用通常類型便可,好比NULL、VARCHAR或OTHER。 | JdbcType常量.大多都爲:NULL,VARCHARandOTHER | OTHER |
lazyLoadTriggerMethods | 指定哪一個對象的方法觸發一次延遲加載。 | 用逗號分隔的方法列表。 | equals,clone,hashCode,toString |
defaultScriptingLanguage | 指定動態SQL生成的默認語言。 | 一個類型別名或徹底限定類名。 | org.apache.ibatis.scripting.xmltags.XMLLanguageDriver |
defaultEnumTypeHandler | 指定Enum使用的默認TypeHandler。(從3.4.5開始) | 一個類型別名或徹底限定類名。 | org.apache.ibatis.type.EnumTypeHandler |
callSettersOnNulls | 指定當結果集中值爲null的時候是否調用映射對象的setter(map對象時爲put)方法,這對於有Map.keySet()依賴或null值初始化的時候是有用的。注意基本類型(int、boolean等)是不能設置成null的。 | true|false | false |
returnInstanceForEmptyRow | 當返回行的全部列都是空時,MyBatis默認返回null。當開啓這個設置時,MyBatis會返回一個空實例。請注意,它也適用於嵌套的結果集(i.e.collectioinandassociation)。(從3.4.2開始) | true|false | false |
logPrefix | 指定MyBatis增長到日誌名稱的前綴。 | 任何字符串 | Notset |
logImpl | 指定MyBatis所用日誌的具體實現,未指定時將自動查找。 | SLF4J|LOG4J|LOG4J2|JDK_LOGGING|COMMONS_LOGGING|STDOUT_LOGGING|NO_LOGGING | Notset |
proxyFactory | 指定Mybatis建立具備延遲加載能力的對象所用到的代理工具。 | CGLIB|JAVASSIST | JAVASSIST(MyBatis3.3orabove) |
vfsImpl | 指定VFS的實現 | 自定義VFS的實現的類全限定名,以逗號分隔。 | Notset |
useActualParamName | 容許使用方法簽名中的名稱做爲語句參數名稱。爲了使用該特性,你的工程必須採用Java8編譯,而且加上-parameters選項。(從3.4.1開始) | true|false | true |
configurationFactory | 指定一個提供Configuration實例的類。這個被返回的Configuration實例用來加載被反序列化對象的懶加載屬性值。這個類必須包含一個簽名方法staticConfigurationgetConfiguration().(從3.2.3版本開始) | 類型別名或者全類名. | Notset |
因爲類的徹底限定名稱比較長,大量使用時十分不方便。MyBatis經過別名的方式來表明它,在MyBatis中別名是不區分大小寫。別名又分爲系統定義別名和自定義別名。
配置自定義別名:
<typeAliases> <!--全寫--> <typeAlias type="com.lzx.entity.Author" alias="author" /> <typeAlias type="com.lzx.entity.Blog" alias="blog" /> <!--簡寫,MyBatis自動掃描這個包下面的全部類,把第一字母變成小寫做爲別名--> <package name="com.lzx.entity" /> </typeAliases>
使用註解配置別名:
@Alias("blog") public class Blog { ... }
系統自定義別名:
別名 | 映射的類型 |
---|---|
_byte | byte |
_long | long |
_short | short |
_int | int |
_integer | int |
_double | double |
_float | float |
_boolean | boolean |
string | String |
byte | Byte |
long | Long |
short | Short |
int | Integer |
integer | Integer |
double | Double |
float | Float |
boolean | Boolean |
date | Date |
decimal | BigDecimal |
bigdecimal | BigDecimal |
object | Object |
map | Map |
hashmap | HashMap |
list | List |
arraylist | ArrayList |
collection | Collection |
iterator | Iterator |
在JDBC中,須要在PreparedStatement中處理預編譯的SQL語句中的參數,執行完畢SQL後,經過ResultSet對象得到數據庫中的數據,這些數據類型在MyBatis中經過typeHandler實現。在typeHandler中分爲jdbcType和javaType。jdbcType定義數據庫類型,javaType定義java類型。typeHandler的做用是承擔jdbcType和javaType之間的相互轉換。通常來講,系統定義的typeHandler就足夠咱們使用,咱們還能夠自定義typeHandler來處理咱們須要知足的轉換規則。
系統定義的typeHandler:
類型處理器 | Java類型 | JDBC類型 |
---|---|---|
BooleanTypeHandler | java.lang.Boolean,boolean | 數據庫兼容的BOOLEAN |
ByteTypeHandler | java.lang.Byte,byte | 數據庫兼容的NUMERIC或BYTE |
ShortTypeHandler | java.lang.Short,short | 數據庫兼容的NUMERIC或SHORTINTEGER |
IntegerTypeHandler | java.lang.Integer,int | 數據庫兼容的NUMERIC或INTEGER |
LongTypeHandler | java.lang.Long,long | 數據庫兼容的NUMERIC或LONGINTEGER |
FloatTypeHandler | java.lang.Float,float | 數據庫兼容的NUMERIC或FLOAT |
DoubleTypeHandler | java.lang.Double,double | 數據庫兼容的NUMERIC或DOUBLE |
BigDecimalTypeHandler | java.math.BigDecimal | 數據庫兼容的NUMERIC或DECIMAL |
StringTypeHandler | java.lang.String | CHAR,VARCHAR |
ClobReaderTypeHandler | java.io.Reader | - |
ClobTypeHandler | java.lang.String | CLOB,LONGVARCHAR |
NStringTypeHandler | java.lang.String | NVARCHAR,NCHAR |
NClobTypeHandler | java.lang.String | NCLOB |
BlobInputStreamTypeHandler | java.io.InputStream | - |
ByteArrayTypeHandler | byte[] | 數據庫兼容的字節流類型 |
BlobTypeHandler | byte[] | BLOB,LONGVARBINARY |
DateTypeHandler | java.util.Date | TIMESTAMP |
DateOnlyTypeHandler | java.util.Date | DATE |
TimeOnlyTypeHandler | java.util.Date | TIME |
SqlTimestampTypeHandler | java.sql.Timestamp | TIMESTAMP |
SqlDateTypeHandler | java.sql.Date | DATE |
SqlTimeTypeHandler | java.sql.Time | TIME |
ObjectTypeHandler | Any | OTHER或未指定類型 |
EnumTypeHandler | EnumerationType | VARCHAR-任何兼容的字符串類型,存儲枚舉的名稱(而不是索引) |
EnumOrdinalTypeHandler | EnumerationType | 任何兼容的NUMERIC或DOUBLE類型,存儲枚舉的索引(而不是名稱)。 |
InstantTypeHandler | java.time.Instant | TIMESTAMP |
LocalDateTimeTypeHandler | java.time.LocalDateTime | TIMESTAMP |
LocalDateTypeHandler | java.time.LocalDate | DATE |
LocalTimeTypeHandler | java.time.LocalTime | TIME |
OffsetDateTimeTypeHandler | java.time.OffsetDateTime | TIMESTAMP |
OffsetTimeTypeHandler | java.time.OffsetTime | TIME |
ZonedDateTimeTypeHandler | java.time.ZonedDateTime | TIMESTAMP |
YearTypeHandler | java.time.Year | INTEGER |
MonthTypeHandler | java.time.Month | INTEGER |
YearMonthTypeHandler | java.time.YearMonth | VARCHARorLONGVARCHAR |
JapaneseDateTypeHandler | java.time.chrono.JapaneseDate | DATE |
自定義typeHandler須要實現TypeHandler接口
public class MyTypeHandler implements TypeHandler<Integer> { // ...重寫方法 }
配置自定義typeHandler:
<typeHandlers> <typeHandler handler="com.lzx.element.MyTypeHandler" javaType="string" jdbcType="VARCHAR" /> <!--掃描包配置typeHandler--> <package name="com.lzx.mytypehandler" /> </typeHandlers>
使用包掃描和註解註冊typeHandler
@MappedTypes(Integer.class) @MappedJdbcTypes(jdbcType.VARCHAR) public class MyTypeHandler implements TypeHandler<Integer> { // ...重寫方法 }
使用自定義typeHandler
<!--使用方式一--> <resultMap id="authorMapper" type="author"> <id property="id" column="id"/> <result property="name" column="name" typeHandler="com.lzx.element.MyTypeHandler"/> </resultMap> <!--使用方式二--> <select id="queryByName" > select `id`,`name` from author where `name` = #{name, typeHandler=com.lzx.element.MyTypeHandler} </select>
枚舉typeHandler
大多數狀況下,typeHandler由於枚舉而使用,MyBatis定義了兩個類做爲枚舉類型地支持,由於不經常使用,因此咱們瞭解一下便可。分別是EnumOrdinalTypeHandler和EnumTypeHandler。其中,EnumOrdinalTypeHandler是按照MyBatis根據數組下標索引的方式進行匹配的,它要求數據庫返回一個整數做爲其下標,它會根據下標找到對應的枚舉類型。 EnumTypeHandler會把使用的名稱轉換爲對應的枚舉,好比它根據數據庫返回的字符串「MALE」進行Enum.valueOf(SexEnum.class,「MALE」)轉換。
文件操做
MyBatis對數據的Blob的字段進行了支持,提供了一個BlobTypeHandler,還有ByteArrayTypeHanddler,只不過不太經常使用。由於一次性把大批量的數據加載到JVM中,會對服務器形成很大的壓力,應該考慮採用文件流的形式。由於性能不佳,大型互聯網網站會採用文件服務器的形式,可以對文件進行更爲告訴的操做。
MyBatis 每次建立結果對象的新實例時,它都會使用一個對象工廠(ObjectFactory)實例來完成。MyBatis容許自定義ObjectFactory,能夠繼承ObjectFactory來實現,可是因爲裏面的自定義返回規則比較複雜且易出錯,因此咱們繼承系統實現好的ObjectFactory便可。
public class MyObjectFactory extends DefaultObjectFactory { // .....重寫方法 }
XML配置:
<objectFactory type="com.lzx.element.MyObjectFactory"> <property name="properties" value="properties_value"/> </objectFactory>
插件是MyBatis中最爲強大和靈活的組件,也是最爲複雜、最難使用的組件。由於它覆蓋了MyBatis底層對象的核心方法和屬性,若是不熟悉MyBatis底層的構建和運行原理,請不要隨意自定義使用。
MyBatis 容許使用插件來攔截的方法調用包括:
自定義插件:
@Intercepts({@Signature( type= Executor.class, method = "update", args = {MappedStatement.class,Object.class})}) public class MyPlugin implements Interceptor { @Override public Object intercept(Invocation invocation) throws Throwable { return null; } @Override public Object plugin(Object o) { return null; } @Override public void setProperties(Properties properties) { } }
XML配置:
<plugins> <plugin interceptor="com.lzx.element.MyPlugin"> <property name="someProperty" value="100"/> </plugin> </plugins>
運行環境主要用來配置數據庫信息,能夠配置多個數據庫。主要分爲兩個配置元素transactionManager(事務管理器)和dataSource(數據庫)。
<environments default="development"> <environment id="decelopment"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="${jdbc.driver}"/> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> </dataSource> </environment> </environments>
在 MyBatis 中有兩種類型的事務管理器(也就是 type=」[JDBC|MANAGED]」):
JDBC – 這個配置就是直接使用了 JDBC 的提交和回滾設置,它依賴於從數據源獲得的鏈接來管理事務做用域。
MANAGED – 這個配置幾乎沒作什麼。它歷來不提交或回滾一個鏈接,而是讓容器來管理事務的整個生命週期(好比 JEE 應用服務器的上下文)。 默認狀況下它會關閉鏈接,然而一些容器並不但願這樣,所以須要將 closeConnection 屬性設置爲 false 來阻止它默認的關閉行爲。
<transactionManager type="MANAGED"> <property name="closeConnection" value="false"/> </transactionManager>
dataSource三種數據源及其屬性:
MyBatis 能夠根據不一樣的數據庫廠商執行不一樣的語句,這種多廠商的支持是基於映射語句中的 databaseId 屬性。 MyBatis 會加載不帶 databaseId 屬性和帶有匹配當前數據庫 databaseId 屬性的全部語句。 若是同時找到帶有 databaseId 和不帶 databaseId 的相同語句,則後者會被捨棄。
<databaseIdProvider type="DB_VENDOR"> <property name="SQL Server" value="sqlserver"/> <property name="DB2" value="db2"/> <property name="Oracle" value="oracle" /> </databaseIdProvider>
使用時,須要在映射器中加上databaseId
<select id="queryByName" resultType="com.lzx.entity.Author" databaseId="oracle"> select * from author where name = #{name} </select>
前面咱們知道實現映射器經常使用的實現方式是聲明一個接口並配合xml文件使用。映射器中的定義命名空間(namespace),命名空間對應的是一個接口的全路徑。
在配置文件中咱們要引入映射器,共有如下幾種實現方式:
1. 使用相對於類路徑的資源引用
2. 使用徹底限定資源定位符(URL)
3. 使用映射器接口實現類的徹底限定類名
4. 將包內的映射器接口實現所有註冊爲映射器
<!--方式一--> <mappers> <mapper resource="mapper/AuthorMapper.xml"/> <mapper resource="mapper/BlogMapper.xml"/> </mappers> <!--方式二--> <mappers> <mapper url="file:///var/mapper/AuthorMapper.xml"/> <mapper url="file:///var/mapper/BlogMapper.xml"/> </mappers> <!--方式三--> <mappers> <mapper class="mapper.AuthorMapper"/> <mapper class="mapper.BlogMapper"/> </mappers> <!--方式四--> <mappers> <package name="mapper"/> </mappers>