帶你學習Mybatis之Mybatis全局配置文件

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 | falsetrue
lazyLoadingEnabled延遲加載的全局開關。當開啟時,所有關聯對象都會延遲加載。 特定關聯關系中可通過設置 fetchType 屬性來覆蓋該項的開關狀態。true | falsefalse
aggressiveLazyLoading開啟時,任一方法的調用都會加載該對象的所有延遲加載屬性。 否則,每個延遲加載屬性會按需加載(參考 lazyLoadTriggerMethods)。true | falsefalse (在 3.4.1 及之前的版本中默認為 true)
multipleResultSetsEnabled是否允許單個語句返回多結果集(需要數據庫驅動支持)。true | falsetrue
useColumnLabel使用列標簽代替列名。實際表現依賴于數據庫驅動,具體可參考數據庫驅動的相關文檔,或通過對比測試來觀察。true | falsetrue
useGeneratedKeys允許 JDBC 支持自動生成主鍵,需要數據庫驅動支持。如果設置為 true,將強制使用自動生成主鍵。盡管一些數據庫驅動不支持此特性,但仍可正常工作(如 Derby)。true | falseFalse
autoMappingBehavior指定 MyBatis 應如何自動映射列到字段或屬性。
NONE 表示關閉自動映射;
PARTIAL 只會自動映射沒有定義嵌套結果映射的字段;
FULL 會自動映射任何復雜的結果集(無論是否嵌套)
NONE, PARTIAL, FULLPARTIAL
autoMappingUnknownColumnBehavior指定發現自動映射目標未知列(或未知屬性類型)的行為。
NONE: 不做任何反應
WARNING: 輸出警告日志('org.apache.ibatis.session.AutoMappingUnknownColumnBehavior' 的日志等級必須設置為 WARN
FAILING: 映射失敗 (拋出 SqlSessionException)
NONE, WARNING, FAILINGNONE
defaultExecutorType配置默認的執行器。
SIMPLE 就是普通的執行器;
REUSE 執行器會重用預處理語句(PreparedStatement);
BATCH 執行器不僅重用語句還會執行批量更新。
SIMPLE REUSE BATCHSIMPLE
defaultStatementTimeout設置超時時間,它決定數據庫驅動等待數據庫響應的秒數。任意正整數未設置 (null)
defaultFetchSize為驅動的結果集獲取數量(fetchSize)設置一個建議值。此參數只可以在查詢設置中被覆蓋。任意正整數未設置 (null)
defaultResultSetType指定語句默認的滾動策略。(新增于 3.5.2)FORWARD_ONLY | SCROLL_SENSITIVE | SCROLL_INSENSITIVE | DEFAULT(等同于未設置)未設置 (null)
safeRowBoundsEnabled是否允許在嵌套語句中使用分頁(RowBounds)。如果允許使用則設置為 false。true | falseFalse
safeResultHandlerEnabled是否允許在嵌套語句中使用結果處理器(ResultHandler)。如果允許使用則設置為 false。true | falseTrue
mapUnderscoreToCamelCase是否開啟駝峰命名自動映射,即從經典數據庫列名 A_COLUMN 映射到經典 Java 屬性名 aColumn。true | falseFalse
localCacheScopeMyBatis 利用本地緩存機制(Local Cache)防止循環引用和加速重復的嵌套查詢。 默認值為 SESSION,會緩存一個會話中執行的所有查詢。 若設置值為 STATEMENT,本地緩存將僅用于執行語句,對相同 SqlSession 的不同查詢將不會進行緩存。SESSION | STATEMENTSESSION
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 | falsefalse
returnInstanceForEmptyRow當返回行的所有列都是空時,MyBatis默認返回 null。 當開啟這個設置時,MyBatis會返回一個空實例。 請注意,它也適用于嵌套的結果集(如集合或關聯)。(新增于 3.4.2)true | falsefalse
logPrefix指定 MyBatis 增加到日志名稱的前綴。任何字符串未設置
logImpl指定 MyBatis 所用日志的具體實現,未指定時將自動查找。SLF4J | LOG4J | LOG4J2 | JDK_LOGGING | COMMONS_LOGGING | STDOUT_LOGGING | NO_LOGGING未設置
proxyFactory指定 Mybatis 創建可延遲加載對象所用到的代理工具。CGLIB | JAVASSISTJAVASSIST (MyBatis 3.3 以上)
vfsImpl指定 VFS 的實現自定義 VFS 的實現的類全限定名,以逗號分隔。未設置
useActualParamName允許使用方法簽名中的名稱作為語句參數名稱。 為了使用該特性,你的項目必須采用 Java 8 編譯,并且加上 -parameters 選項。(新增于 3.4.1)true | falsetrue
configurationFactory指定一個提供 Configuration 實例的類。 這個被返回的 Configuration 實例用來加載被反序列化對象的延遲加載屬性值。 這個類必須包含一個簽名為static Configuration getConfiguration() 的方法。(新增于 3.2.3)一個類型別名或完全限定類名。未設置
shrinkWhitespacesInSql從SQL中刪除多余的空格字符。請注意,這也會影響SQL中的文字字符串。 (新增于 3.5.5)true | falsefalse
defaultSqlProviderTypeSpecifies 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 nameNot 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 多平臺發布

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/19654.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/19654.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/19654.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

車載以太網的未來:OPEN Alliance下17個技術委員會的最新進展與行業影響(下)

從上篇介紹來看&#xff0c;TC1-TC8大多數處于暫停或完成狀態。而TC9-TC17在2023年都有不同程度的進展&#xff0c;讓我們繼續探索藏在其中的車載以太網的發展和挑戰。 TC9 Automotive Ethernet Channel & Components&#xff08;in progress&#xff09; TC9的目標是為通…

[初始計算機]——計算機網絡的基本概念和發展史及OSI參考模型

&#x1f3e1;作者主頁&#xff1a;點擊&#xff01; &#x1f916;網絡通信基礎TCP/IP專欄&#xff1a;點擊&#xff01; ??創作時間&#xff1a;2024年5月30日11點59分 &#x1f004;?文章質量&#xff1a;96分 ? 目錄 &#x1f310;計算機網絡概述 &#x1f4af;…

opencv是什么?它有什么功能和特性?它值不值得我們去學習?我們該如何去學習呢?

1.opencv是什么&#xff1f; OpenCV&#xff08;Open Source Computer Vision Library&#xff09;是一個開源的計算機視覺庫&#xff0c;旨在提供一系列豐富的圖像處理和計算機視覺算法&#xff0c;以及用于構建實時圖像處理和機器視覺應用程序的開發工具。它最初由英特爾開發…

使用QT可視化操作信號與槽函數詳解

新書上架~&#x1f447;全國包郵奧~ python實用小工具開發教程http://pythontoolsteach.com/3 歡迎關注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目錄 一、引言 二、QT信號與槽機制概述 三、實際操作步驟 四、案例演示 五、總結 一、引言 在…

中國養生保健元宇宙-探索養生保健新領域

在全球化和科技迅速發展的今天&#xff0c;元宇宙作為一種全新的互聯網應用和社會形態&#xff0c;正逐步滲透到人們生活的各個方面。特別是在養生保健領域&#xff0c;中國的元宇宙概念正在引領一場革命&#xff0c;將古老的養生智慧與現代科技完美融合&#xff0c;為人們打造…

單片機建立自己的庫文件(1)

文章目錄 前言一、代碼模塊化是什么&#xff1f;二、使用步驟1.以LCD1602作為例子2.將LCD1602 相關的代碼抽取到另外一個文件中 三、調用LCD1602.h1.新建一個工程項目&#xff0c;將LCD1602.h添加到工程中2.在主函數上加入 #include <LCD1602.h> 總結 前言 提示&#xf…

進口鋁合金電動隔膜泵

進口鋁合金電動隔膜泵是一種高效、可靠的工業泵&#xff0c;其特點、性能與應用廣泛&#xff0c;以下是對其的詳細分析&#xff1a; 特點 材質與結構&#xff1a; 采用鋁合金材料制造&#xff0c;具有良好的耐腐蝕性和輕量化特點。鋁合金材質使得泵體結構緊湊、輕便&#xff…

svg實現一個圓形以及方形的環形進度條

1. svg實現圓形進度條 效果圖&#xff1a; 1. 寫個假接口&#xff1a; let res {curLegendList: [{ progress: "87", name: "進度1",color:"#00fe41" },{ progress: "66", name: "進度2" ,color:"orange"},{ p…

gitlab服務器遷移(親測有效)

描述&#xff1a;最近公司遷移gitlab&#xff0c;我沒有遷移過&#xff0c;經過網上查找資料最終完成遷移&#xff0c;途中也遇到挺多坑和兩個問題&#xff0c;希望能幫到你。 新服務器安裝gitlab 注意&#xff1a;新服務器gitlab版本也需要和舊版本一致。 首先查看原Gitlab…

基于Python實現地震數據可視化的設計與實現

基于Python實現地震數據可視化的設計與實現 “Design and Implementation of Earthquake Data Visualization using Python” 完整下載鏈接:基于Python實現地震數據可視化的設計與實現 文章目錄 基于Python實現地震數據可視化的設計與實現摘要第一章 引言1.1 研究背景1.2 研究…

RabbitMQ(三)SpringBoot整合,可靠性投遞,死信隊列,延遲隊列,消費端限流,消息超時

文章目錄 整合Springboot概述消費者生產者 消息可靠性投遞故障原因解決方案生產者端消息確認機制&#xff08;故障情況1&#xff09;故障情況2解決方案故障情況3解決方案 消費端限流概念 消息超時概念隊列層面&#xff1a;配置隊列過期消息本身&#xff1a;配置消息過期 死信隊…

C++中的虛函數和純虛函數

目錄 摘要 虛函數&#xff08;Virtual Functions&#xff09; 定義 用法 純虛函數&#xff08;Pure Virtual Functions&#xff09; 定義 用法 需要避開的坑 總結 摘要 在C中&#xff0c;我們經常會在開發中使用到虛函數&#xff08;Virtual Functions&#xff09;和…

如何有效屏蔽手機上的騷擾電話20240530

如何有效屏蔽手機上的騷擾電話 引言 最近&#xff0c;我的手機經常接到954開頭的7位數字座機電話&#xff0c;這些騷擾電話讓我非常困擾。由于我經常點外賣&#xff0c;無法屏蔽所有陌生號碼&#xff0c;因此需要一個既能屏蔽特定前綴的騷擾電話&#xff0c;又不影響日常生活…

英偉達(NVIDIA)H100性能及應用場景

英偉達H100是一款性能強大的GPU芯片&#xff0c;其關鍵性能參數和應用領域可以歸納如下&#xff1a; 一、性能參數 架構&#xff1a;H100采用了新一代的Hopper架構&#xff0c;擁有高達1.8萬億次/秒的張量處理能力和高達840 TFLOPS的FP8張量性能。CUDA核心數&#xff1a;H100…

STM32學習和實踐筆記(33):待機喚醒實驗

1.STM32待機模式介紹 很多單片機具有低功耗模式&#xff0c;比如MSP430、STM8L等&#xff0c;我們的STM32也不例外。默認情況下&#xff0c;系統復位或上電復位后&#xff0c;微控制器進入運行模式。在運行模式下&#xff0c;HCLK 為CPU提供時鐘&#xff0c;并執行程序代碼。這…

kafka學習筆記06

Kafka數據存儲流程和log日志講解 講解分布式應用核心CAP知識 Kafka數據可靠性保證原理之副本機制Replica介紹《上》 Kafka數據可靠性保證原理之副本機制Replica介紹《下》 Kafka數據可靠性保證原理之ISR機制講解 Kafka的HighWatermark的作用你知道多少

暑期來臨,AI智能視頻分析方案筑牢防溺水安全屏障

隨著夏季暑期的來臨&#xff0c;未成年人溺水事故頻發。傳統的防溺水方式往往依賴于人工巡邏和警示標識的設置&#xff0c;但這種方式存在人力不足、反應速度慢等局限性。近年來&#xff0c;隨著視頻監控智能分析技術的不斷發展&#xff0c;其在夏季防溺水中的應用也日益凸顯出…

ubuntu22 搭建nginx高可用集群(VIP(keepalived) + 負載均衡)

#在所有節點安裝nginx #ps: 如果要使用tcp流轉發&#xff1a;需用二進制包安裝 make編譯時加入stream流的參數。 推薦直接安裝openresty【默認支持stream等nginx模塊&#xff0c;還附帶了很多常用的lua庫】 apt install -y net-tools sudo apt install -y nginx vim /etc/…

恒創科技:無法與服務器建立安全連接怎么解決?

在使用互聯網服務時&#xff0c;有時會出現無法與服務器建立安全連接的問題&#xff0c;此錯誤消息通常出現在嘗試訪問需要安全連接的網站(例如使用 HTTPS 的網站)時&#xff0c;這可能是由于多種原因造成的&#xff0c;以下是一些常見的解決方法&#xff0c;幫助你解決問題。 …

聚道云軟件連接器:打通易快報與保融資金系統,實現高效財務管理

一、客戶介紹&#xff1a;食品企業&#xff0c;引領健康零食新風尚 某食品行業的公司作為國內領先的集研發、生產、銷售為一體的現代化辣味休閑食品企業。該公司秉承“健康、美味、安全”的理念&#xff0c;不斷創新和進取&#xff0c;為消費者帶來了一系列美味可口的辣味休閑…