Mybatis全局配置文件
<?xml?version="1.0"?encoding="UTF-8"?>
<configuration>?<!--?配置?-->
????<properties/>?<!--?屬性?-->
????<settings/>?<!--?設置?-->
????<typeAliases/>?<!--?類型別名?-->
????<typeHandlers/>?<!--?類型處理器?-->
????<objectFactory/>?<!--?對象工廠?-->
???<plugins/>?<!--?插件?-->
????<!--?環境?default表示默認使用環境??-->
????<environments?default="development">?<!--?配置環境?-->
????????<environment?id="development">?<!--?環境變量?-->
????????????<transactionManager?type="JDBC"/>?<!--?事務管理器?-->
???????????<dataSource?type="UNPOOLED"/>?<!--?數據源?-->
????????</environment>
????</environments>
????<!--?數據庫廠商標識?-->
????<databaseIdProvider?type="DB_VENDOR"/>
????????
????<!--?mapper配置?-->
????<mappers/>
????
</configuration>
配置properties屬性
可以在全局配置文件中配置properties標簽來進行外部配置
設置屬性的方式有三種
-
在properties的屬性節點resource或url所指定的資源文件中配置
-
在properties的子節點property中配置
-
在構建SqlSessionFactory時通過方法傳入參數
外部配置文件引入
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/test
jdbc.username=root
jdbc.password=123456
<!--?使用?properties來引入外部配置文件內容-->
<!--?resource??引入類路徑下的資源
?????url??引入網路或磁盤路徑下的資源
?-->
<properties?resource="jdbc.properties">
</properties>
property子節點配置
<!--?也可以使用property子節點來進行配置?-->
<properties?resource="jdbc.properties">
????<property?name="jdbc.password"?value="123456"/>
????<!--?啟用默認值特性?-->
????<property?name="org.apache.ibatis.parsing.PropertyParser.enable-default-value"?value="true"/>
????<!--?修改默認值的分隔符?-->
????<property?name="org.apache.ibatis.parsing.PropertyParser.default-value-separator"?value="?:"/>
</properties>
實例化時方法傳參
public?static?SqlSessionFactory?createFactory(){
????//?獲取到mybatis-config.xml配置文件,進而構建SqlSessionFactory
????InputStream?is?=?Thread.currentThread().getContextClassLoader().getResourceAsStream("mybatis-config.xml");
????Properties?props?=?new?Properties();
????props.put("jdbc.password","123456");
????return?new?SqlSessionFactoryBuilder().build(is,props);
}
使用
使用${}來引用配置好的屬性值
<!--?數據庫配置?-->
<environments?default="development">
????<environment?id="development">
????????<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="org.apache.ibatis.parsing.PropertyParser.enable-default-value"?value="true"/>
?????????????如果開啟該特性,默認使用:分隔
?????????????可以使用?????????<property?name="org.apache.ibatis.parsing.PropertyParser.default-value-separator"?value="?:"/>
?????????????來修改默認分隔符
?????????????-->
????????????<property?name="password"?value="${jdbc.password?:123456}"/>
????????</dataSource>
????</environment>
</environments>
三種方式的順序
-
首先讀取property子節點中指定的屬性 -
再讀取使用resources或url引入的外部配置文件中屬性,并覆蓋之前的同名屬性 -
最后讀取作為方法傳遞的參數,并覆蓋之前的同名屬性
配置settings設置
mybatis中有很多默認的配置,可以使用settings來進行mybatis的自定義設置,覆蓋掉mybatis中的默認配置
設置名 | 描述 | 有效值 | 默認值 |
---|---|---|---|
cacheEnabled | 全局性地開啟或關閉所有映射器配置文件中已配置的任何緩存。 | true | false | true |
lazyLoadingEnabled | 延遲加載的全局開關。當開啟時,所有關聯對象都會延遲加載。 特定關聯關系中可通過設置 fetchType 屬性來覆蓋該項的開關狀態。 | true | false | false |
aggressiveLazyLoading | 開啟時,任一方法的調用都會加載該對象的所有延遲加載屬性。 否則,每個延遲加載屬性會按需加載(參考 lazyLoadTriggerMethods )。 | true | false | false (在 3.4.1 及之前的版本中默認為 true) |
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 : 輸出警告日志('org.apache.ibatis.session.AutoMappingUnknownColumnBehavior' 的日志等級必須設置為 WARN )FAILING : 映射失敗 (拋出 SqlSessionException ) | NONE, WARNING, FAILING | NONE |
defaultExecutorType | 配置默認的執行器。 SIMPLE 就是普通的執行器; REUSE 執行器會重用預處理語句(PreparedStatement); BATCH 執行器不僅重用語句還會執行批量更新。 | SIMPLE REUSE BATCH | SIMPLE |
defaultStatementTimeout | 設置超時時間,它決定數據庫驅動等待數據庫響應的秒數。 | 任意正整數 | 未設置 (null) |
defaultFetchSize | 為驅動的結果集獲取數量(fetchSize)設置一個建議值。此參數只可以在查詢設置中被覆蓋。 | 任意正整數 | 未設置 (null) |
defaultResultSetType | 指定語句默認的滾動策略。(新增于 3.5.2) | FORWARD_ONLY | SCROLL_SENSITIVE | SCROLL_INSENSITIVE | DEFAULT(等同于未設置) | 未設置 (null) |
safeRowBoundsEnabled | 是否允許在嵌套語句中使用分頁(RowBounds)。如果允許使用則設置為 false。 | true | false | False |
safeResultHandlerEnabled | 是否允許在嵌套語句中使用結果處理器(ResultHandler)。如果允許使用則設置為 false。 | true | false | True |
mapUnderscoreToCamelCase | 是否開啟駝峰命名自動映射,即從經典數據庫列名 A_COLUMN 映射到經典 Java 屬性名 aColumn。 | true | false | False |
localCacheScope | MyBatis 利用本地緩存機制(Local Cache)防止循環引用和加速重復的嵌套查詢。 默認值為 SESSION,會緩存一個會話中執行的所有查詢。 若設置值為 STATEMENT,本地緩存將僅用于執行語句,對相同 SqlSession 的不同查詢將不會進行緩存。 | SESSION | STATEMENT | SESSION |
jdbcTypeForNull | 當沒有為參數指定特定的 JDBC 類型時,空值的默認 JDBC 類型。 某些數據庫驅動需要指定列的 JDBC 類型,多數情況直接用一般類型即可,比如 NULL、VARCHAR 或 OTHER。 | JdbcType 常量,常用值:NULL、VARCHAR 或 OTHER。 | 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會返回一個空實例。 請注意,它也適用于嵌套的結果集(如集合或關聯)。(新增于 3.4.2) | true | false | false |
logPrefix | 指定 MyBatis 增加到日志名稱的前綴。 | 任何字符串 | 未設置 |
logImpl | 指定 MyBatis 所用日志的具體實現,未指定時將自動查找。 | SLF4J | LOG4J | LOG4J2 | JDK_LOGGING | COMMONS_LOGGING | STDOUT_LOGGING | NO_LOGGING | 未設置 |
proxyFactory | 指定 Mybatis 創建可延遲加載對象所用到的代理工具。 | CGLIB | JAVASSIST | JAVASSIST (MyBatis 3.3 以上) |
vfsImpl | 指定 VFS 的實現 | 自定義 VFS 的實現的類全限定名,以逗號分隔。 | 未設置 |
useActualParamName | 允許使用方法簽名中的名稱作為語句參數名稱。 為了使用該特性,你的項目必須采用 Java 8 編譯,并且加上 -parameters 選項。(新增于 3.4.1) | true | false | true |
configurationFactory | 指定一個提供 Configuration 實例的類。 這個被返回的 Configuration 實例用來加載被反序列化對象的延遲加載屬性值。 這個類必須包含一個簽名為static Configuration getConfiguration() 的方法。(新增于 3.2.3) | 一個類型別名或完全限定類名。 | 未設置 |
shrinkWhitespacesInSql | 從SQL中刪除多余的空格字符。請注意,這也會影響SQL中的文字字符串。 (新增于 3.5.5) | true | false | false |
defaultSqlProviderType | Specifies an sql provider class that holds provider method (Since 3.5.6). This class apply to the type (or value ) attribute on sql provider annotation(e.g. @SelectProvider ), when these attribute was omitted. | A type alias or fully qualified class name | Not set |
????<settings>
????????<!--?開啟二級緩存?-->
????????<setting?name="cacheEnabled"?value="true"/>
????????<setting?name="logImpl"?value="STDOUT_LOGGING"/>
????????<!--?延遲加載的全局開關。當開啟時,所有關聯對象都會延遲加載。?特定關聯關系中可通過設置?fetchType?屬性來覆蓋該項的開關狀態。?-->
????????<setting?name="lazyLoadingEnabled"?value="true"/>
????????<!--?開啟時,任一方法的調用都會加載該對象的所有延遲加載屬性。?否則,每個延遲加載屬性會按需加載?-->
????????<setting?name="aggressiveLazyLoading"?value="false"/>
????</settings>
也可以使用java實現
Configuration?configuration?=?new?Configuration();
configuration.setCacheEnabled(true);
配置typeAliases類型別名
由于在配置resultMap、resultType、parameterType的時候可能會用到類的全類名,而全類名一般又很長,可以為類來設置別名
系統定義別名
Mybatis中定義了一些經常使用的類型別名
//TypeAliasRegistry類中
registerAlias("string",?String.class);
registerAlias("byte",?Byte.class);
registerAlias("long",?Long.class);
registerAlias("short",?Short.class);
registerAlias("int",?Integer.class);
registerAlias("integer",?Integer.class);
registerAlias("double",?Double.class);
registerAlias("float",?Float.class);
registerAlias("boolean",?Boolean.class);
registerAlias("byte[]",?Byte[].class);
registerAlias("long[]",?Long[].class);
registerAlias("short[]",?Short[].class);
registerAlias("int[]",?Integer[].class);
registerAlias("integer[]",?Integer[].class);
registerAlias("double[]",?Double[].class);
registerAlias("float[]",?Float[].class);
registerAlias("boolean[]",?Boolean[].class);
registerAlias("_byte",?byte.class);
registerAlias("_long",?long.class);
registerAlias("_short",?short.class);
registerAlias("_int",?int.class);
registerAlias("_integer",?int.class);
registerAlias("_double",?double.class);
registerAlias("_float",?float.class);
registerAlias("_boolean",?boolean.class);
registerAlias("_byte[]",?byte[].class);
registerAlias("_long[]",?long[].class);
registerAlias("_short[]",?short[].class);
registerAlias("_int[]",?int[].class);
registerAlias("_integer[]",?int[].class);
registerAlias("_double[]",?double[].class);
registerAlias("_float[]",?float[].class);
registerAlias("_boolean[]",?boolean[].class);
registerAlias("date",?Date.class);
registerAlias("decimal",?BigDecimal.class);
registerAlias("bigdecimal",?BigDecimal.class);
registerAlias("biginteger",?BigInteger.class);
registerAlias("object",?Object.class);
registerAlias("date[]",?Date[].class);
registerAlias("decimal[]",?BigDecimal[].class);
registerAlias("bigdecimal[]",?BigDecimal[].class);
registerAlias("biginteger[]",?BigInteger[].class);
registerAlias("object[]",?Object[].class);
registerAlias("map",?Map.class);
registerAlias("hashmap",?HashMap.class);
registerAlias("list",?List.class);
registerAlias("arraylist",?ArrayList.class);
registerAlias("collection",?Collection.class);
registerAlias("iterator",?Iterator.class);
registerAlias("ResultSet",?ResultSet.class);
自定義別名
類型別名可以為java類型設置別名,之后使用全類名時可以使用別名
<typeAliases>
????<!--?typeAlias為某個類起別名?-->
????<typeAlias?type="com.zhanghe.study.mybatis.model.User"?alias="User"/>
????
????<!--?為某個包下所有類批量起別名
????????默認值為類名首字母小寫
?????-->
????<package?name="com.zhanghe.study.mybatis.model"/>
</typeAliases>
也可以在類上使用@Alias注解來設置該類的別名
也可以使用java來實現
Configuration?configuration?=?new?Configuration();
configuration.getTypeAliasRegistry().registerAlias("User",?User.class);
//?注冊整個包
configuration.getTypeAliasRegistry().registerAliases("com.zhanghe.study.mybatis.model");
配置typeHandlers類型處理器
作用是將參數從javaType轉化為jdbcType,或者從數據庫中取出結果時把jdbcType轉化為javaType
在使用原生JDBC的時候使用PreparedStatement來設置參數時,是需要自己根據不同的類型來使用不同的方法的
String?sql?=?"insert?into?user?(name)?values?(?)";
statement?=?conn.prepareStatement(sql);
statement.setString(1,name);
那么mybatis如何知道該使用什么方法呢,這里就用到了typeHandlers
系統定義typeHandler
mybatis中有很多類型處理器,對于所有的基本數據類型、基本數據類型包裝類、byte[]、java.util.Date、java.sql.Date、java.sql.Time、java.sql.TimeStamp、java枚舉等。
//?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(Reader.class,?new?ClobReaderTypeHandler());
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?StringTypeHandler());
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?StringTypeHandler());
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(InputStream.class,?new?BlobInputStreamTypeHandler());
register(Byte[].class,?new?ByteObjectArrayTypeHandler());
register(Byte[].class,?JdbcType.BLOB,?new?BlobByteObjectArrayTypeHandler());
register(Byte[].class,?JdbcType.LONGVARBINARY,?new?BlobByteObjectArrayTypeHandler());
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,?unknownTypeHandler);
register(Object.class,?JdbcType.OTHER,?unknownTypeHandler);
register(JdbcType.OTHER,?unknownTypeHandler);
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());
register(String.class,?JdbcType.SQLXML,?new?SqlxmlTypeHandler());
register(Instant.class,?new?InstantTypeHandler());
register(LocalDateTime.class,?new?LocalDateTimeTypeHandler());
register(LocalDate.class,?new?LocalDateTypeHandler());
register(LocalTime.class,?new?LocalTimeTypeHandler());
register(OffsetDateTime.class,?new?OffsetDateTimeTypeHandler());
register(OffsetTime.class,?new?OffsetTimeTypeHandler());
register(ZonedDateTime.class,?new?ZonedDateTimeTypeHandler());
register(Month.class,?new?MonthTypeHandler());
register(Year.class,?new?YearTypeHandler());
register(YearMonth.class,?new?YearMonthTypeHandler());
register(JapaneseDate.class,?new?JapaneseDateTypeHandler());
//?issue?#273
register(Character.class,?new?CharacterTypeHandler());
register(char.class,?new?CharacterTypeHandler());
自定義typeHandler
也可以來自定義一個typeHandler,通過實現 org.apache.ibatis.type.TypeHandler 接口, 或繼承 org.apache.ibatis.type.BaseTypeHandler, 并且可以將它映射到一個 JDBC 類型
@MappedTypes({String.class})?//?定義的是javaType類型,可以指定哪些java類型被攔截
@MappedJdbcTypes(JdbcType.VARCHAR)?//?定義的是jdbcType類型
public?class?ExampleTypeHandler?extends?BaseTypeHandler<String>?{
??@Override
??public?void?setNonNullParameter(PreparedStatement?ps,?int?i,?String?parameter,?JdbcType?jdbcType)?throws?SQLException?{
????ps.setString(i,?parameter);
??}
??@Override
??public?String?getNullableResult(ResultSet?rs,?String?columnName)?throws?SQLException?{
????return?rs.getString(columnName);
??}
??@Override
??public?String?getNullableResult(ResultSet?rs,?int?columnIndex)?throws?SQLException?{
????return?rs.getString(columnIndex);
??}
??@Override
??public?String?getNullableResult(CallableStatement?cs,?int?columnIndex)?throws?SQLException?{
????return?cs.getString(columnIndex);
??}
}
<typeHandlers>
??<typeHandler?handler="org.mybatis.example.ExampleTypeHandler"/>
</typeHandlers>
也可以使用java實現
Configuration?configuration?=?new?Configuration();
//?第一個參數為java類型??第二個參數為TypeHandler類
configuration.getTypeHandlerRegistry().register(String.class,?StringTypeHandler.class);
配置objectFactory對象工廠
每次 MyBatis 創建結果對象的新實例時,它都會使用一個ObjectFactory實例來完成實例化工作。 默認的objectFactory(DefaultObjectFactory)需要做的僅僅是實例化目標類,要么通過默認無參構造方法,要么通過存在的參數映射來調用帶有參數的構造方法。 如果想覆蓋對象工廠的默認行為,可以通過創建自己的對象工廠來實現
public?interface?ObjectFactory?{
??//?配置ObjectFactory,設置屬性
??default?void?setProperties(Properties?properties)?{
????//?NOP
??}
??//?使用無參構造器
??<T>?T?create(Class<T>?type);
??//?使用有參構造器
??<T>?T?create(Class<T>?type,?List<Class<?>>?constructorArgTypes,?List<Object>?constructorArgs);
??
??<T>?boolean?isCollection(Class<T>?type);
}
繼承DefaultObjectFactory類
public?class?ExampleObjectFactory?extends?DefaultObjectFactory?{
??public?Object?create(Class?type)?{
????return?super.create(type);
??}
??public?Object?create(Class?type,?List<Class>?constructorArgTypes,?List<Object>?constructorArgs)?{
????return?super.create(type,?constructorArgTypes,?constructorArgs);
??}
??public?void?setProperties(Properties?properties)?{
????super.setProperties(properties);
??}
??public?<T>?boolean?isCollection(Class<T>?type)?{
????return?Collection.class.isAssignableFrom(type);
??}
}
<objectFactory?type="org.mybatis.example.ExampleObjectFactory">
??<property?name="someProperty"?value="100"/>
</objectFactory>
配置plugins插件
mybatis可以使用插件來在映射語句執行過程中的某一點進行攔截調用,包括
-
Executor (update、query、flushStatements、commit、rollback、getTransaction、close、isClose) -
ParameterHandler (getParameterObject、setParameters) -
ResultSetHandler (handleResultSets、handleOutputParameters) -
StatementHandler (prepare、parameterize、batch、update、query)
需要實現Interceptor接口,并指定想要攔截的方法簽名來使用插件
Intercepts({@Signature(
??type=?Executor.class,
??method?=?"update",
??args?=?{MappedStatement.class,Object.class})})
public?class?ExamplePlugin?implements?Interceptor?{
??private?Properties?properties?=?new?Properties();
??public?Object?intercept(Invocation?invocation)?throws?Throwable?{
????//?implement?pre?processing?if?need
????Object?returnObject?=?invocation.proceed();
????//?implement?post?processing?if?need
????return?returnObject;
??}
??public?void?setProperties(Properties?properties)?{
????this.properties?=?properties;
??}
}
<plugins>
??<plugin?interceptor="org.mybatis.example.ExamplePlugin">
????<property?name="someProperty"?value="100"/>
??</plugin>
</plugins>
注意:如果有多個插件攔截相同方法的時候,會按照配置的先后順序來進行包裝代理,在執行時會執行最外層的插件,也就是逆向執行
配置environments環境
mybatis可以配置多個環境,可以連接多個數據源,每一個數據源分為兩部分:一個是數據源的配置,一個是數據庫事務的配置,但是每個SqlSessionFactory實例只可以選擇一種環境,如在開發環境、測試環境、生產環境等所用的配置可能不同,如果想要連接兩個數據庫,則需要創建兩個SqlSessionFactory實例
在構建sqlSessionFactory的時候可以指定選擇創建哪個環境,如果不傳入environment,則會使用默認的環境
SqlSessionFactory?factory?=?new?SqlSessionFactoryBuilder().build(reader,?environment);
<!--?環境?default表示默認使用環境??-->
<environments?default="development">
????<environment?id="development">
????????<!--?事務管理器有兩種類型
????????????1、JDBC??內部使用JdbcTransactionFactory來創建transactionManager,由應用程序來管理數據庫連接的生命周期,該配置直接使用了JDBC的提交和回滾,依賴從數據源獲得的連接來管理事務作用域
????????????2、MANAGED?內部使用ManagedTransactionFactory來創建transactionManager,使用容器(應用服務器)來管理事務的整個生命周期
??????(與spring整合使用時,spring會使用自帶的管理器,不需要配置mybatis的事務管理器)
?????????-->
????????<transactionManager?type="JDBC"/>
????????<!--?數據源有三種類型
????????????1、UNPOOLED??每次請求時打開和關閉連接??實現類UnpooledDataSource
????????????????額外屬性??-?defaultTransactionIsolationLevel??默認的連接事務隔離級別
?????????????????????????-?defaultNetworkTimeout??等待數據庫操作完成的默認網絡超時時間
????????????2、POOLED??利用連接池的概念將JDBC連接對象組織起來,避免了創建新的連接實例?實現類PooledDataSource
????????????????額外屬性
????????????????????-?poolMaximumActiveConnections?在任意時間可存在的活動連接數,默認10
????????????????????-?poolMaximumIdleConnections??任意時間可能存在的空閑連接數
????????????????????-?poolMaximumCheckoutTime??在被強制返回之前,池中連接被檢出時間,默認20000毫秒
????????????????????-?poolTimeToWait??如果獲取連接花費了很長的時間,連接池會打印狀態日志并重新嘗試獲取一個連接,默認20000毫秒
????????????????????-?poolMaximumLocalBadConnectionTolerance??如果一個線程獲取到一個壞的連接,數據源允許這個線程嘗試重新獲取一個新的連接,
??????????????????????????????????????????????????????????????嘗試次數不應該超過poolMaximumIdleConnections與poolMaximumLocalBadConnectionTolerance之和,默認為3
????????????????????-?poolPingQuery??發送到數據庫的偵測查詢,用來檢驗連接是否正常工作???默認?NO?PING?QUERY?SET
????????????????????-?poolPingEnabled??是否啟用偵測查詢??默認false
????????????????????-?poolPingConnectionsNotUsedFor??配置poolPingQuery的頻率(可以設置為和數據庫連接超時時間一樣,避免不必要的偵測)??默認0
????????????3、JNDI??在外部配置數據源,然后一個JNDI上下文數據源引用,使用JndiDataSourceFactory來獲取數據源
????????????????額外屬性
????????????????????-?initial_context??用來在InitialContext中尋找上下文
????????????????????-?data_source??引用數據源實例的上下文路徑
?????????-->
????????<dataSource?type="POOLED">
????????????<property?name="driver"?value="${jdbc.driver}"/>
????????????<property?name="url"?value="${jdbc.url}"/>
????????????<property?name="username"?value="${jdbc.username}"/>
????????????<!--?可以使用:來為占位符設置默認值,如果沒有讀取到該屬性的值,會使用該默認值
?????????????該特性默認關閉,需要配置????????<property?name="org.apache.ibatis.parsing.PropertyParser.enable-default-value"?value="true"/>
?????????????如果開啟該特性,默認使用:分隔
?????????????可以使用?????????<property?name="org.apache.ibatis.parsing.PropertyParser.default-value-separator"?value="?:"/>
?????????????來修改默認分隔符
?????????????-->
????????????<property?name="password"?value="${jdbc.password?:123456}"/>
????????</dataSource>
????</environment>
</environments>
也可以實現org.apache.ibatis.datasource.DataSourceFactory接口來自定義數據源實現,然后進行配置
也可以使用Java來編碼實現
DataSource?dataSource?=?new?PooledDataSourceFactory().getDataSource();
//?JDBC實例化JdbcTransactionFactory????MANAGED實例化ManagedTransactionFactory
TransactionFactory?transactionFactory?=?new?JdbcTransactionFactory();
Environment?environment?=?new?Environment("development",transactionFactory,dataSource);
Configuration?configuration?=?new?Configuration(environment);
自定義數據源
實現org.apache.ibatis.datasource.DataSourceFactory接口
配置 databaseIdProvider數據庫廠商標識
mybatis可以根據不同的數據庫廠商執行不同的語句,基于映射語句中的databaseId屬性。mybatis會加載帶有匹配當前數據庫databaseId屬性個所有不帶databaseId屬性的語句。如果同時找到帶有databaseId的不帶databaseId的相同語句,后者會被舍棄
<!--?數據庫廠商標識?
type="DB_VENDOR"?是啟動Mybatis內部注冊的策略器
-->
<databaseIdProvider?type="DB_VENDOR">
??<!--?name為使用DatabaseMetaData#getDatabaseProductName()返回的廠商名稱
?????????????value為所設置的別名,使用databaseId時使用別名即可?-->
??<property?name="MySQL"?value="mysql"/>
??<property?name="Oracle"?value="oracle"/>
</databaseIdProvider>
在mapper.xml中可以使用databaseId配置不同數據庫的sql語句
<!--?查詢數據的方法?-->
<!--?mysql?-->
<select?id="selectUser"?resultType="User"?databaseId="mysql">
????select?*?from?users?where?id?=?#{id}
</select>
<!--?oracle?-->
<select?id="selectUser"?resultType="User"?databaseId="oracle">
????select?*?from?users?where?id?=?#{id}
</select>
可以實現org.apache.ibatis.mapping.DatabaseIdProvider接口自定義DatabaseIdProvider
配置mappers映射器
將寫好的sql映射文件(mapper.xml)注冊到全局配置文件中
<!--?mapper配置?-->
<mappers>
????<!--?resource??引入類路徑classpath下的資源??-->
????<mapper?resource="mapper/UserMapper.xml"/>
????<!--?url??引入網絡或者磁盤路徑下的sql映射文件?指定協議為file或者http?-->
????<mapper?url=""/>
????<!--?class??基于注解的方式,注冊類文件??這種方式要求mapper接口名稱和mapper映射文件名稱相同且在同一個目錄下-->
????<mapper?class="com.zhanghe.study.mybatis.mapper.UserMapper"/>
????<!--?批量注冊?注冊整個包下的?這種方式要求mapper接口名稱和mapper映射文件名稱相同且在同一個目錄-->
????<package?name="com.zhanghe.study.mybatis.mapper"/>
</mappers>
也可以使用java來實現
Configuration?configuration?=?new?Configuration();
configuration.addMapper(User.class);
https://zhhll.icu/2021/框架/mybatis/基礎/2.mybatis全局配置文件/
本文由 mdnice 多平臺發布