Mybatis源码学习-开篇
学习源码前,需要知道框架解决了什么问题,基本用法是什么,然后再去深入研究其内部实现,并能举一反三,灵活运用
mybatis是什么
MyBatis is a first class persistence framework with support for custom SQL, stored procedures and advanced mappings. MyBatis eliminates almost all of the JDBC code and manual setting of parameters and retrieval of results. MyBatis can use simple XML or Annotations for configuration and map primitives, Map interfaces and Java POJOs (Plain Old Java Objects) to database records. -- 摘自官方文档(https://mybatis.org/mybatis-3/index.html)
简单翻一下:
持久层框架
支持自定义SQL、存储过程和高级映射
隐藏了大部分JDBC的代码细节(模板代码、设置参数以及返回值封装)
支持XML以及Java注解配置
支持数据库记录与Java对象的映射
怎么使用
在Maven项目pom文件中添加一下依赖,版本取官方最新版本即可
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>x.x.x</version>
</dependency>
开天辟地-SqlSessionFactory
mybatis所有的数据库操作由SqlSession会话进行管理,而要实例化SqlSession需要使用SqlSessionFactory,创建SqlSessionFactory是由SqlSessionFactoryBuilder产生
String resource = "org/mybatis/example/mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
初始化配置
- xml
mybatis初始化的配置支持xml协议,比如设置数据源、事务管理器等,以下只是一小部分
<?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="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="org/mybatis/example/BlogMapper.xml"/>
</mappers>
</configuration>
- code
当然,mybatis也支持通过代码的方式进行配置的初始化操作
DataSource dataSource = BlogDataSourceFactory.getBlogDataSource();
TransactionFactory transactionFactory = new JdbcTransactionFactory();
Environment environment = new Environment("development", transactionFactory, dataSource);
Configuration configuration = new Configuration(environment);
configuration.addMapper(BlogMapper.class);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(configuration);
执行-SqlSession
真正执行数据库操作的全部由SqlSession来掌控,而SqlSession想要执行真正的数据库操作,肯定离不开SQL语句,mybatis支持xml配置形式以及注解形式来编写你的SQL语句,不过由于xml配置的方式更加灵活而且强大,支持更复杂的SQL聚合,所以官方还是建议以xml的形式来组织你的SQL以及对象的映射关系
<?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="org.mybatis.example.BlogMapper">
<select id="selectBlog" resultType="Blog">
select * from Blog where id = #{id}
</select>
</mapper>
package org.mybatis.example;
public interface BlogMapper {
@Select("SELECT * FROM blog WHERE id = #{id}")
Blog selectBlog(int id);
}
调用执行有两种方式,一种是通过命名空间(namespace)值找到对应的映射SQL,一种是基于mybatis对映射关系的接口代理,后者更加安全和方便
Blog blog = session.selectOne("org.mybatis.example.BlogMapper.selectBlog", 101);
BlogMapper mapper = session.getMapper(BlogMapper.class);
Blog blog = mapper.selectBlog(101);
初始化配置
mybatis核心初始化配置文件包含以下内容:
- properties
- settings
- typeAliases
- typeHandlers
- objectFactory
- plugins
- environments
- environment
- transactionManager
- dataSource
- environment
- databaseIdProvider
- mappers
properties
定义了一些可复用的变量
<properties resource="org/mybatis/example/config.properties">
<property name="username" value="dev_user"/>
<property name="password" value="F2Fa3!33TYyg"/>
</properties>
例如:下面美元符号中引用的变量即为上面定义的部分
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
属性文件加载顺序:
- 指定属性文件
- 类路径或者指定url地址获取的属性
- 方法中进行传递的属性
以上按照加载顺序加载入内存,并且后加载的存在相同属性名称的会覆盖之前加载的属性值
默认值:以下形式冒号后面为当前属性未赋值时的默认值
${username:ut_user}
前提是需要进行配置开启,默认配置是不支持默认值的方式
<properties resource="org/mybatis/example/config.properties">
<!-- ... -->
<property name="org.apache.ibatis.parsing.PropertyParser.enable-default-value" value="true"/> <!-- Enable this feature -->
</properties>
默认值加载是进行分隔符进行拆分,解析进行复制,可能会存在符号冲突,因此如果存在默认值中存在冒号值,你需要修改分隔符
<properties resource="org/mybatis/example/config.properties">
<!-- ... -->
<property name="org.apache.ibatis.parsing.PropertyParser.default-value-separator" value="?:"/> <!-- Change default value of separator -->
</properties>
<dataSource type="POOLED">
<!-- ... -->
<property name="username" value="${db:username?:ut_user}"/>
</dataSource>
settings
mybatis运行时设置参数,如下所示,摘自官方文档(https://mybatis.org/mybatis-3/configuration.html)
Setting | Description | Valid Values | Default |
---|---|---|---|
cacheEnabled | Globally enables or disables any caches configured in any mapper under this configuration. | true | false | true |
lazyLoadingEnabled | Globally enables or disables lazy loading. When enabled, all relations will be lazily loaded. This value can be superseded for a specific relation by using the fetchType attribute on it. |
true | false | false |
aggressiveLazyLoading | When enabled, any method call will load all the lazy properties of the object. Otherwise, each property is loaded on demand (see also lazyLoadTriggerMethods ). |
true | false | false (true in ≤3.4.1) |
multipleResultSetsEnabled | Allows or disallows multiple ResultSets to be returned from a single statement (compatible driver required). | true | false | true |
useColumnLabel | Uses the column label instead of the column name. Different drivers behave differently in this respect. Refer to the driver documentation, or test out both modes to determine how your driver behaves. | true | false | true |
useGeneratedKeys | Allows JDBC support for generated keys. A compatible driver is required. This setting forces generated keys to be used if set to true, as some drivers deny compatibility but still work (e.g. Derby). | true | false | False |
autoMappingBehavior | Specifies if and how MyBatis should automatically map columns to fields/properties. NONE disables auto-mapping. PARTIAL will only auto-map results with no nested result mappings defined inside. FULL will auto-map result mappings of any complexity (containing nested or otherwise). | NONE, PARTIAL, FULL | PARTIAL |
autoMappingUnknownColumnBehavior | Specify the behavior when detects an unknown column (or unknown property type) of automatic mapping target.NONE : Do nothingWARNING : Output warning log (The log level of 'org.apache.ibatis.session.AutoMappingUnknownColumnBehavior' must be set to WARN )FAILING : Fail mapping (Throw SqlSessionException ) |
NONE, WARNING, FAILING | NONE |
defaultExecutorType | Configures the default executor. SIMPLE executor does nothing special. REUSE executor reuses prepared statements. BATCH executor reuses statements and batches updates. | SIMPLE REUSE BATCH | SIMPLE |
defaultStatementTimeout | Sets the number of seconds the driver will wait for a response from the database. | Any positive integer | Not Set (null) |
defaultFetchSize | Sets the driver a hint as to control fetching size for return results. This parameter value can be override by a query setting. | Any positive integer | Not Set (null) |
defaultResultSetType | Specifies a scroll strategy when omit it per statement settings. (Since: 3.5.2) | FORWARD_ONLY | SCROLL_SENSITIVE | SCROLL_INSENSITIVE | DEFAULT(same behavior with 'Not Set') | Not Set (null) |
safeRowBoundsEnabled | Allows using RowBounds on nested statements. If allow, set the false. | true | false | False |
safeResultHandlerEnabled | Allows using ResultHandler on nested statements. If allow, set the false. | true | false | True |
mapUnderscoreToCamelCase | Enables automatic mapping from classic database column names A_COLUMN to camel case classic Java property names aColumn. | true | false | False |
localCacheScope | MyBatis uses local cache to prevent circular references and speed up repeated nested queries. By default (SESSION) all queries executed during a session are cached. If localCacheScope=STATEMENT local session will be used just for statement execution, no data will be shared between two different calls to the same SqlSession. | SESSION | STATEMENT | SESSION |
jdbcTypeForNull | Specifies the JDBC type for null values when no specific JDBC type was provided for the parameter. Some drivers require specifying the column JDBC type but others work with generic values like NULL, VARCHAR or OTHER. | JdbcType enumeration. Most common are: NULL, VARCHAR and OTHER | OTHER |
lazyLoadTriggerMethods | Specifies which Object's methods trigger a lazy load | A method name list separated by commas | equals,clone,hashCode,toString |
defaultScriptingLanguage | Specifies the language used by default for dynamic SQL generation. | A type alias or fully qualified class name. | org.apache.ibatis.scripting.xmltags.XMLLanguageDriver |
defaultEnumTypeHandler | Specifies the TypeHandler used by default for Enum. (Since: 3.4.5) |
A type alias or fully qualified class name. | org.apache.ibatis.type.EnumTypeHandler |
callSettersOnNulls | Specifies if setters or map's put method will be called when a retrieved value is null. It is useful when you rely on Map.keySet() or null value initialization. Note primitives such as (int,boolean,etc.) will not be set to null. | true | false | false |
returnInstanceForEmptyRow | MyBatis, by default, returns null when all the columns of a returned row are NULL. When this setting is enabled, MyBatis returns an empty instance instead. Note that it is also applied to nested results (i.e. collectioin and association). Since: 3.4.2 |
true | false | false |
logPrefix | Specifies the prefix string that MyBatis will add to the logger names. | Any String | Not set |
logImpl | Specifies which logging implementation MyBatis should use. If this setting is not present logging implementation will be autodiscovered. | SLF4J | LOG4J | LOG4J2 | JDK_LOGGING | COMMONS_LOGGING | STDOUT_LOGGING | NO_LOGGING | Not set |
proxyFactory | Specifies the proxy tool that MyBatis will use for creating lazy loading capable objects. | CGLIB | JAVASSIST | JAVASSIST (MyBatis 3.3 or above) |
vfsImpl | Specifies VFS implementations | Fully qualified class names of custom VFS implementation separated by commas. | Not set |
useActualParamName | Allow referencing statement parameters by their actual names declared in the method signature. To use this feature, your project must be compiled in Java 8 with -parameters option. (Since: 3.4.1) |
true | false | true |
configurationFactory | Specifies the class that provides an instance of Configuration . The returned Configuration instance is used to load lazy properties of deserialized objects. This class must have a method with a signature static Configuration getConfiguration() . (Since: 3.2.3) |
A type alias or fully qualified class name. | Not set |
shrinkWhitespacesInSql | Removes extra whitespace characters from the SQL. Note that this also affects literal strings in SQL. (Since 3.5.5) | true | false | false |
xml配置
<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>
后续源码分析时,会针对性进行分析
typeAliases
类型别名,针对Java类的别名设置,简化调用
指定类,并进行别名设置
<typeAliases>
<typeAlias alias="Author" type="domain.blog.Author"/>
<typeAlias alias="Blog" type="domain.blog.Blog"/>
<typeAlias alias="Comment" type="domain.blog.Comment"/>
<typeAlias alias="Post" type="domain.blog.Post"/>
<typeAlias alias="Section" type="domain.blog.Section"/>
<typeAlias alias="Tag" type="domain.blog.Tag"/>
</typeAliases>
指定包名,配合注解进行别名设置
<typeAliases>
<package name="domain.blog"/>
</typeAliases>
@Alias("author")
public class Author {
...
}
如果包下未指定注解,则取类名首字母小写(Author --> author)
内建别名
mybatis内建了一批基础别名设置,原始类型前面添加了_下划线,其余均是首字母小写形式
Alias | Mapped Type |
---|---|
_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 |
typeHandlers
mybatis进行对象与数据库记录映射需要进行类型转换,主要发挥作用的就是TypeHandler,TypeHandler定义了解析接口,具体实现交由各个映射关系的解析器去实现,用户可自定义类型处理器来处理mybatis没有实现的类型转换
Type Handler | Java Types | JDBC Types |
---|---|---|
BooleanTypeHandler |
java.lang.Boolean , boolean
|
Any compatible BOOLEAN
|
ByteTypeHandler |
java.lang.Byte , byte
|
Any compatible NUMERIC or BYTE
|
ShortTypeHandler |
java.lang.Short , short
|
Any compatible NUMERIC or SMALLINT
|
IntegerTypeHandler |
java.lang.Integer , int
|
Any compatible NUMERIC or INTEGER
|
LongTypeHandler |
java.lang.Long , long
|
Any compatible NUMERIC or BIGINT
|
FloatTypeHandler |
java.lang.Float , float
|
Any compatible NUMERIC or FLOAT
|
DoubleTypeHandler |
java.lang.Double , double
|
Any compatible NUMERIC or DOUBLE
|
BigDecimalTypeHandler |
java.math.BigDecimal |
Any compatible NUMERIC or 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[] |
Any compatible byte stream type |
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 , or unspecified |
EnumTypeHandler |
Enumeration Type |
VARCHAR any string compatible type, as the code is stored (not index). |
EnumOrdinalTypeHandler |
Enumeration Type | Any compatible NUMERIC or DOUBLE , as the position is stored (not the code itself). |
SqlxmlTypeHandler |
java.lang.String |
SQLXML |
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 |
VARCHAR or LONGVARCHAR
|
JapaneseDateTypeHandler |
java.time.chrono.JapaneseDate |
DATE |
自定义
实现
// ExampleTypeHandler.java
@MappedJdbcTypes(value = JdbcType.VARCHAR, includeNullJdbcType = true)
@MappedTypes(String.class)
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);
}
}
加载自定义实现
<!-- mybatis-config.xml -->
<typeHandlers>
<typeHandler handler="org.mybatis.example.ExampleTypeHandler" javaType="String" jdbcType="VARCHAR"/>
</typeHandlers>
自定义的类型处理器如果存在内建支持的类型,则会覆盖mybatis默认实现,这一点请在实现的时候进行注意,还有一点值得注意的地方是在配置文件中指定了转换类型的时候,加载时会忽略注解的对应指定类型
也可以执行包名配合注解形式加载类型处理器
<!-- mybatis-config.xml -->
<typeHandlers>
<package name="org.mybatis.example"/>
</typeHandlers>
objectFactory
对象生成工厂类,主要用来实例化类
plugins
mybatis拦截器-允许用户对执行过程添加自己的实现逻辑,能够处理的地方只有指定几个地方:
- Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)
- ParameterHandler (getParameterObject, setParameters)
- ResultSetHandler (handleResultSets, handleOutputParameters)
- StatementHandler (prepare, parameterize, batch, update, query)
在自定义插件的时候一定要熟悉每一个组件的含义,以及逻辑的影响点,不然可能导致不可预期的副作用
// ExamplePlugin.java
@Intercepts({@Signature(
type= Executor.class,
method = "update",
args = {MappedStatement.class,Object.class})})
public class ExamplePlugin implements Interceptor {
private Properties properties = new Properties();
@Override
public Object intercept(Invocation invocation) throws Throwable {
// implement pre-processing if needed
Object returnObject = invocation.proceed();
// implement post-processing if needed
return returnObject;
}
@Override
public void setProperties(Properties properties) {
this.properties = properties;
}
}
<!-- mybatis-config.xml -->
<plugins>
<plugin interceptor="org.mybatis.example.ExamplePlugin">
<property name="someProperty" value="100"/>
</plugin>
</plugins>
environments
支持不同环境设置不同的数据库连接,每个环境只允许设置一个,方便区分环境配置
<environments default="development">
<environment id="development">
<transactionManager type="JDBC">
<property name="..." value="..."/>
</transactionManager>
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
</environment>
</environments>
关键配置
transactionManager-事务管理器
- JDBC 默认配置
- MANAGED 集成第三方事务管理器,包含了关闭连接的默认设置,可以设置关闭
<transactionManager type="MANAGED">
<property name="closeConnection" value="false"/>
</transactionManager>
dataSource- 数据源
- UNPOOLED 无池化数据源
- POOLED 池化数据源
- JNDI
自定义数据源实现
public interface DataSourceFactory {
void setProperties(Properties props);
DataSource getDataSource();
}
databaseIdProvider
提供数据库厂商ID的支持(DatabaseMetaData#getDatabaseProductName())
<databaseIdProvider type="DB_VENDOR">
<property name="SQL Server" value="sqlserver"/>
<property name="DB2" value="db2"/>
<property name="Oracle" value="oracle" />
</databaseIdProvider>
自定义
public interface DatabaseIdProvider {
default void setProperties(Properties p) { // Since 3.5.2, changed to default method
// NOP
}
String getDatabaseId(DataSource dataSource) throws SQLException;
}
mappers
SQL的映射配置的加载方式配置
<!-- Using classpath relative resources -->
<mappers>
<mapper resource="org/mybatis/builder/AuthorMapper.xml"/>
<mapper resource="org/mybatis/builder/BlogMapper.xml"/>
<mapper resource="org/mybatis/builder/PostMapper.xml"/>
</mappers>
<!-- Using url fully qualified paths -->
<mappers>
<mapper url="file:///var/mappers/AuthorMapper.xml"/>
<mapper url="file:///var/mappers/BlogMapper.xml"/>
<mapper url="file:///var/mappers/PostMapper.xml"/>
</mappers>
<!-- Using mapper interface classes -->
<mappers>
<mapper class="org.mybatis.builder.AuthorMapper"/>
<mapper class="org.mybatis.builder.BlogMapper"/>
<mapper class="org.mybatis.builder.PostMapper"/>
</mappers>
<!-- Register all interfaces in a package as mappers -->
<mappers>
<package name="org.mybatis.builder"/>
</mappers>
映射配置
初始化配置中配置好了加载SQL映射文件或者包名的路径后,mybatis会读取配置文件或者解析类构件SQL映射关系
-
cache
– Configuration of the cache for a given namespace. -
cache-ref
– Reference to a cache configuration from another namespace. -
resultMap
– The most complicated and powerful element that describes how to load your objects from the database result sets. parameterMap
– Deprecated! Old-school way to map parameters. Inline parameters are preferred and this element may be removed in the future. Not documented here.-
sql
– A reusable chunk of SQL that can be referenced by other statements. -
insert
– A mapped INSERT statement. -
update
– A mapped UPDATE statement. -
delete
– A mapped DELETE statement. -
select
– A mapped SELECT statement.
select
查询SQL
<select id="selectPerson" parameterType="int" resultType="hashmap">
SELECT * FROM PERSON WHERE ID = #{id}
</select>
=
// Similar JDBC code, NOT MyBatis…
String selectPerson = "SELECT * FROM PERSON WHERE ID=?";
PreparedStatement ps = conn.prepareStatement(selectPerson);
ps.setInt(1,id);
包含属性
Attribute | Description |
---|---|
id |
A unique identifier in this namespace that can be used to reference this statement. |
parameterType |
The fully qualified class name or alias for the parameter that will be passed into this statement. This attribute is optional because MyBatis can calculate the TypeHandler to use out of the actual parameter passed to the statement. Default is unset . |
parameterMap |
This is a deprecated approach to referencing an external parameterMap . Use inline parameter mappings and the parameterType attribute. |
resultType |
The fully qualified class name or alias for the expected type that will be returned from this statement. Note that in the case of collections, this should be the type that the collection contains, not the type of the collection itself. Use resultType OR resultMap , not both. |
resultMap |
A named reference to an external resultMap . Result maps are the most powerful feature of MyBatis, and with a good understanding of them, many difficult mapping cases can be solved. Use resultMap OR resultType , not both. |
flushCache |
Setting this to true will cause the local and 2nd level caches to be flushed whenever this statement is called. Default: false for select statements. |
useCache |
Setting this to true will cause the results of this statement to be cached in 2nd level cache. Default: true for select statements. |
timeout |
This sets the number of seconds the driver will wait for the database to return from a request, before throwing an exception. Default is unset (driver dependent). |
fetchSize |
This is a driver hint that will attempt to cause the driver to return results in batches of rows numbering in size equal to this setting. Default is unset (driver dependent). |
statementType |
Any one of STATEMENT , PREPARED or CALLABLE . This causes MyBatis to use Statement , PreparedStatement or CallableStatement respectively. Default: PREPARED . |
resultSetType |
Any one of FORWARD_ONLY SCROLL_SENSITIVE SCROLL_INSENSITIVE DEFAULT (same as unset). Default is unset (driver dependent). |
databaseId |
In case there is a configured databaseIdProvider, MyBatis will load all statements with no databaseId attribute or with a databaseId that matches the current one. If case the same statement if found with and without the databaseId the latter will be discarded. |
resultOrdered |
This is only applicable for nested result select statements: If this is true, it is assumed that nested results are contained or grouped together such that when a new main result row is returned, no references to a previous result row will occur anymore. This allows nested results to be filled much more memory friendly. Default: false . |
resultSets |
This is only applicable for multiple result sets. It lists the result sets that will be returned by the statement and gives a name to each one. Names are separated by commas. |
insert, update and delete
更新SQL
Attribute | Description |
---|---|
id |
A unique identifier in this namespace that can be used to reference this statement. |
parameterType |
The fully qualified class name or alias for the parameter that will be passed into this statement. This attribute is optional because MyBatis can calculate the TypeHandler to use out of the actual parameter passed to the statement. Default is unset . |
parameterMap |
This is a deprecated approach to referencing an external parameterMap. Use inline parameter mappings and the parameterType attribute. |
flushCache |
Setting this to true will cause the 2nd level and local caches to be flushed whenever this statement is called. Default: true for insert, update and delete statements. |
timeout |
This sets the maximum number of seconds the driver will wait for the database to return from a request, before throwing an exception. Default is unset (driver dependent). |
statementType |
Any one of STATEMENT , PREPARED or CALLABLE . This causes MyBatis to use Statement , PreparedStatement or CallableStatement respectively. Default: PREPARED . |
useGeneratedKeys |
(insert and update only) This tells MyBatis to use the JDBC getGeneratedKeys method to retrieve keys generated internally by the database (e.g. auto increment fields in RDBMS like MySQL or SQL Server). Default: false . |
keyProperty |
(insert and update only) Identifies a property into which MyBatis will set the key value returned by getGeneratedKeys , or by a selectKey child element of the insert statement. Default: unset . Can be a comma separated list of property names if multiple generated columns are expected. |
keyColumn |
(insert and update only) Sets the name of the column in the table with a generated key. This is only required in certain databases (like PostgreSQL) when the key column is not the first column in the table. Can be a comma separated list of columns names if multiple generated columns are expected. |
databaseId |
In case there is a configured databaseIdProvider, MyBatis will load all statements with no databaseId attribute or with a databaseId that matches the current one. If case the same statement if found with and without the databaseId the latter will be discarded. |
案例
<!-- 自增主键 -->
<insert id="insertAuthor" useGeneratedKeys="true"
keyProperty="id">
insert into Author (username,password,email,bio)
values (#{username},#{password},#{email},#{bio})
</insert>
<!-- 批量插入 -->
<insert id="insertAuthor" useGeneratedKeys="true"
keyProperty="id">
insert into Author (username, password, email, bio) values
<foreach item="item" collection="list" separator=",">
(#{item.username}, #{item.password}, #{item.email}, #{item.bio})
</foreach>
</insert>
<insert id="insertAuthor">
<!-- 支持自定义主键生成 -->
<selectKey keyProperty="id" resultType="int" order="BEFORE">
select CAST(RANDOM()*1000000 as INTEGER) a from SYSIBM.SYSDUMMY1
</selectKey>
insert into Author
(id, username, password, email,bio, favourite_section)
values
(#{id}, #{username}, #{password}, #{email}, #{bio}, #{favouriteSection,jdbcType=VARCHAR})
</insert>
selectKey
Attribute | Description |
---|---|
keyProperty |
The target property where the result of the selectKey statement should be set. Can be a comma separated list of property names if multiple generated columns are expected. |
keyColumn |
The column name(s) in the returned result set that match the properties. Can be a comma separated list of column names if multiple generated columns are expected. |
resultType |
The type of the result. MyBatis can usually figure this out, but it doesn't hurt to add it to be sure. MyBatis allows any simple type to be used as the key, including Strings. If you are expecting multiple generated columns, then you can use an Object that contains the expected properties, or a Map. |
order |
This can be set to BEFORE or AFTER . If set to BEFORE , then it will select the key first, set the keyProperty and then execute the insert statement. If set to AFTER , it runs the insert statement and then the selectKey statement – which is common with databases like Oracle that may have embedded sequence calls inside of insert statements. |
statementType |
Same as above, MyBatis supports STATEMENT , PREPARED and CALLABLE statement types that map to Statement , PreparedStatement and CallableStatement respectively. |
sql
可复用SQL
<sql id="userColumns"> ${alias}.id,${alias}.username,${alias}.password </sql>
<select id="selectUsers" resultType="map">
select
<!-- 引用SQL节点 -->
<include refid="userColumns"><property name="alias" value="t1"/></include>,
<include refid="userColumns"><property name="alias" value="t2"/></include>
from some_table t1
cross join some_table t2
</select>
Parameters
SQL具体的参数变量
#{property,javaType=int,jdbcType=NUMERIC}
#{age,javaType=int,jdbcType=NUMERIC,typeHandler=MyTypeHandler}
#{height,javaType=double,jdbcType=NUMERIC,numericScale=2}
#{department, mode=OUT, jdbcType=CURSOR, javaType=ResultSet, resultMap=departmentResultMap}
#{middleInitial, mode=OUT, jdbcType=STRUCT, jdbcTypeName=MY_TYPE, resultMap=departmentResultMap}
String Substitution
常量替换(美元符号)
${stringSubstitution}
Result Maps
数据库字段与Java对象映射关系
<select id="selectUsers" resultType="com.someapp.model.User">
select id, username, hashedPassword
from some_table
where id = #{id}
</select>
<!-- In Config XML file -->
<typeAlias type="com.someapp.model.User" alias="User"/>
<!-- In SQL Mapping XML file -->
<select id="selectUsers" resultType="User">
select id, username, hashedPassword
from some_table
where id = #{id}
</select>
<select id="selectUsers" resultType="User">
select
user_id as "id",
user_name as "userName",
hashed_password as "hashedPassword"
from some_table
where id = #{id}
</select>
<resultMap id="userResultMap" type="User">
<id property="id" column="user_id" />
<result property="username" column="user_name"/>
<result property="password" column="hashed_password"/>
</resultMap>
<select id="selectUsers" resultMap="userResultMap">
select user_id, user_name, hashed_password
from some_table
where id = #{id}
</select>
Advanced Result Maps
高级映射配置
<!-- Very Complex Result Map -->
<resultMap id="detailedBlogResultMap" type="Blog">
<constructor>
<idArg column="blog_id" javaType="int"/>
</constructor>
<result property="title" column="blog_title"/>
<association property="author" javaType="Author">
<id property="id" column="author_id"/>
<result property="username" column="author_username"/>
<result property="password" column="author_password"/>
<result property="email" column="author_email"/>
<result property="bio" column="author_bio"/>
<result property="favouriteSection" column="author_favourite_section"/>
</association>
<collection property="posts" ofType="Post">
<id property="id" column="post_id"/>
<result property="subject" column="post_subject"/>
<association property="author" javaType="Author"/>
<collection property="comments" ofType="Comment">
<id property="id" column="comment_id"/>
</collection>
<collection property="tags" ofType="Tag" >
<id property="id" column="tag_id"/>
</collection>
<discriminator javaType="int" column="draft">
<case value="1" resultType="DraftPost"/>
</discriminator>
</collection>
</resultMap>
resultMap
子节点
-
constructor
- used for injecting results into the constructor of a class upon instantiation-
idArg
- ID argument; flagging results as ID will help improve overall performance -
arg
- a normal result injected into the constructor
-
id
– an ID result; flagging results as ID will help improve overall performanceresult
– a normal result injected into a field or JavaBean property-
association
– a complex type association; many results will roll up into this type- nested result mappings – associations are
resultMap
s themselves, or can refer to one
- nested result mappings – associations are
-
collection
– a collection of complex types- nested result mappings – collections are
resultMap
s themselves, or can refer to one
- nested result mappings – collections are
discriminator
– uses a result value to determine which resultMap
to use
- case – a case is a result map based on some value
- nested result mappings – a case is also a result map itself, and thus can contain many of these same elements, or it can refer to an external resultMap.
属性
Attribute | Description |
---|---|
id |
A unique identifier in this namespace that can be used to reference this result map. |
type |
A fully qualified Java class name, or a type alias (see the table above for the list of built-in type aliases). |
autoMapping |
If present, MyBatis will enable or disable the automapping for this ResultMap. This attribute overrides the global autoMappingBehavior. Default: unset. |
id & result
Attribute | Description |
---|---|
property |
The field or property to map the column result to. If a matching JavaBeans property exists for the given name, then that will be used. Otherwise, MyBatis will look for a field of the given name. In both cases you can use complex property navigation using the usual dot notation. For example, you can map to something simple like: username , or to something more complicated like: address.street.number . |
column |
The column name from the database, or the aliased column label. This is the same string that would normally be passed to resultSet.getString(columnName) . |
javaType |
A fully qualified Java class name, or a type alias (see the table above for the list of built-in type aliases). MyBatis can usually figure out the type if you're mapping to a JavaBean. However, if you are mapping to a HashMap, then you should specify the javaType explicitly to ensure the desired behaviour. |
jdbcType |
The JDBC Type from the list of supported types that follows this table. The JDBC type is only required for nullable columns upon insert, update or delete. This is a JDBC requirement, not a MyBatis one. So even if you were coding JDBC directly, you'd need to specify this type – but only for nullable values. |
typeHandler |
We discussed default type handlers previously in this documentation. Using this property you can override the default type handler on a mapping-by-mapping basis. The value is either a fully qualified class name of a TypeHandler implementation, or a type alias. |
Supported JDBC Types
BIT |
FLOAT |
CHAR |
TIMESTAMP |
OTHER |
UNDEFINED |
---|---|---|---|---|---|
TINYINT |
REAL |
VARCHAR |
BINARY |
BLOB |
NVARCHAR |
SMALLINT |
DOUBLE |
LONGVARCHAR |
VARBINARY |
CLOB |
NCHAR |
INTEGER |
NUMERIC |
DATE |
LONGVARBINARY |
BOOLEAN |
NCLOB |
BIGINT |
DECIMAL |
TIME |
NULL |
CURSOR |
ARRAY |
constructor
构造器传参实例化对象,无name属性必须按照顺序寻找构造器,有name属性必须指定编译选项(-parameters)
<constructor>
<idArg column="id" javaType="int" name="id" />
<arg column="age" javaType="_int" name="age" />
<arg column="username" javaType="String" name="username" />
</constructor>
属性
Attribute | Description |
---|---|
column |
The column name from the database, or the aliased column label. This is the same string that would normally be passed to resultSet.getString(columnName) . |
javaType |
A fully qualified Java class name, or a type alias (see the table above for the list of built-in type aliases). MyBatis can usually figure out the type if you're mapping to a JavaBean. However, if you are mapping to a HashMap, then you should specify the javaType explicitly to ensure the desired behaviour. |
jdbcType |
The JDBC Type from the list of supported types that follows this table. The JDBC type is only required for nullable columns upon insert, update or delete. This is a JDBC requirement, not an MyBatis one. So even if you were coding JDBC directly, you'd need to specify this type – but only for nullable values. |
typeHandler |
We discussed default type handlers previously in this documentation. Using this property you can override the default type handler on a mapping-by-mapping basis. The value is either a fully qualified class name of a TypeHandler implementation, or a type alias. |
select |
The ID of another mapped statement that will load the complex type required by this property mapping. The values retrieved from columns specified in the column attribute will be passed to the target select statement as parameters. See the Association element for more. |
resultMap |
This is the ID of a ResultMap that can map the nested results of this argument into an appropriate object graph. This is an alternative to using a call to another select statement. It allows you to join multiple tables together into a single ResultSet . Such a ResultSet will contain duplicated, repeating groups of data that needs to be decomposed and mapped properly to a nested object graph. To facilitate this, MyBatis lets you "chain" result maps together, to deal with the nested results. See the Association element below for more. |
name |
The name of the constructor parameter. Specifying name allows you to write arg elements in any order. See the above explanation. Since 3.4.3. |
association
1:1关联记录 "has-one"
Attribute | Description |
---|---|
property |
The field or property to map the column result to. If a matching JavaBeans property exists for the given name, then that will be used. Otherwise, MyBatis will look for a field of the given name. In both cases you can use complex property navigation using the usual dot notation. For example, you can map to something simple like: username , or to something more complicated like: address.street.number . |
javaType |
A fully qualified Java class name, or a type alias (see the table above for the list of built- in type aliases). MyBatis can usually figure out the type if you're mapping to a JavaBean. However, if you are mapping to a HashMap , then you should specify the javaType explicitly to ensure the desired behaviour. |
jdbcType |
The JDBC Type from the list of supported types that follows this table. The JDBC type is only required for nullable columns upon insert, update or delete. This is a JDBC requirement, not an MyBatis one. So even if you were coding JDBC directly, you'd need to specify this type – but only for nullable values. |
typeHandler |
We discussed default type handlers previously in this documentation. Using this property you can override the default type handler on a mapping-by-mapping basis. The value is either a fully qualified class name of a TypeHandler implementation, or a type alias. |
Nested Select for Association
级联查询
Attribute | Description |
---|---|
column |
The column name from the database, or the aliased column label that holds the value that will be passed to the nested statement as an input parameter. This is the same string that would normally be passed to resultSet.getString(columnName) . Note: To deal with composite keys, you can specify multiple column names to pass to the nested select statement by using the syntax column="{prop1=col1,prop2=col2}" . This will cause prop1 and prop2 to be set against the parameter object for the target nested select statement. |
select |
The ID of another mapped statement that will load the complex type required by this property mapping. The values retrieved from columns specified in the column attribute will be passed to the target select statement as parameters. A detailed example follows this table. Note: To deal with composite keys, you can specify multiple column names to pass to the nested select statement by using the syntax column="{prop1=col1,prop2=col2}" . This will cause prop1 and prop2 to be set against the parameter object for the target nested select statement. |
fetchType |
Optional. Valid values are lazy and eager . If present, it supersedes the global configuration parameter lazyLoadingEnabled for this mapping. |
<resultMap id="blogResult" type="Blog">
<association property="author" column="author_id" javaType="Author" select="selectAuthor"/>
</resultMap>
<select id="selectBlog" resultMap="blogResult">
SELECT * FROM BLOG WHERE ID = #{id}
</select>
<select id="selectAuthor" resultType="Author">
SELECT * FROM AUTHOR WHERE ID = #{id}
</select>
上述方式会导致经典的N+1问题
Nested Results for Association
关联查询
Attribute | Description |
---|---|
resultMap |
This is the ID of a ResultMap that can map the nested results of this association into an appropriate object graph. This is an alternative to using a call to another select statement. It allows you to join multiple tables together into a single ResultSet. Such a ResultSet will contain duplicated, repeating groups of data that needs to be decomposed and mapped properly to a nested object graph. To facilitate this, MyBatis lets you "chain" result maps together, to deal with the nested results. An example will be far easier to follow, and one follows this table. |
columnPrefix |
When joining multiple tables, you would have to use column alias to avoid duplicated column names in the ResultSet. Specifying columnPrefix allows you to map such columns to an external resultMap. Please see the example explained later in this section. |
notNullColumn |
By default a child object is created only if at least one of the columns mapped to the child's properties is non null. With this attribute you can change this behaviour by specifiying which columns must have a value so MyBatis will create a child object only if any of those columns is not null. Multiple column names can be specified using a comma as a separator. Default value: unset. |
autoMapping |
If present, MyBatis will enable or disable automapping when mapping the result to this property. This attribute overrides the global autoMappingBehavior. Note that it has no effect on an external resultMap, so it is pointless to use it with select or resultMap attribute. Default value: unset. |
配置
<resultMap id="blogResult" type="Blog">
<id property="id" column="blog_id" />
<result property="title" column="blog_title"/>
<association property="author" resultMap="authorResult" />
</resultMap>
<resultMap id="authorResult" type="Author">
<id property="id" column="author_id"/>
<result property="username" column="author_username"/>
<result property="password" column="author_password"/>
<result property="email" column="author_email"/>
<result property="bio" column="author_bio"/>
</resultMap>
<!-- 或者写在一起 -->
<resultMap id="blogResult" type="Blog">
<id property="id" column="blog_id" />
<result property="title" column="blog_title"/>
<association property="author" javaType="Author">
<id property="id" column="author_id"/>
<result property="username" column="author_username"/>
<result property="password" column="author_password"/>
<result property="email" column="author_email"/>
<result property="bio" column="author_bio"/>
</association>
</resultMap>
<!-- 复用 -->
<resultMap id="blogResult" type="Blog">
<id property="id" column="blog_id" />
<result property="title" column="blog_title"/>
<association property="author" resultMap="authorResult" />
<!-- 复用authorResult并添加前缀映射 -->
<association property="coAuthor" resultMap="authorResult" columnPrefix="co_" />
</resultMap>
sql
<select id="selectBlog" resultMap="blogResult">
select
B.id as blog_id,
B.title as blog_title,
B.author_id as blog_author_id,
A.id as author_id,
A.username as author_username,
A.password as author_password,
A.email as author_email,
A.bio as author_bio
from Blog B left outer join Author A on B.author_id = A.id
where B.id = #{id}
</select>
Multiple ResultSets for Association
返回多个结果集
Attribute | Description |
---|---|
column |
When using multiple resultset this attribute specifies the columns (separated by commas) that will be correlated with the foreignColumn to identify the parent and the child of a relationship. |
foreignColumn |
Identifies the name of the columns that contains the foreign keys which values will be matched against the values of the columns specified in the column attibute of the parent type. |
resultSet |
Identifies the name of the result set where this complex type will be loaded from. |
<select id="selectBlog" resultSets="blogs,authors" resultMap="blogResult" statementType="CALLABLE">
{call getBlogsAndAuthors(#{id,jdbcType=INTEGER,mode=IN})}
</select>
<resultMap id="blogResult" type="Blog">
<id property="id" column="id" />
<result property="title" column="title"/>
<association property="author" javaType="Author" resultSet="authors" column="author_id" foreignColumn="id">
<id property="id" column="id"/>
<result property="username" column="username"/>
<result property="password" column="password"/>
<result property="email" column="email"/>
<result property="bio" column="bio"/>
</association>
</resultMap>
collection
一对多映射( "has many")
<collection property="posts" ofType="domain.blog.Post">
<id property="id" column="post_id"/>
<result property="subject" column="post_subject"/>
<result property="body" column="post_body"/>
</collection>
Nested Select for Collection
嵌套级联查询
<resultMap id="blogResult" type="Blog">
<collection property="posts" javaType="ArrayList" column="id" ofType="Post" select="selectPostsForBlog"/>
</resultMap>
<select id="selectBlog" resultMap="blogResult">
SELECT * FROM BLOG WHERE ID = #{id}
</select>
<select id="selectPostsForBlog" resultType="Post">
SELECT * FROM POST WHERE BLOG_ID = #{id}
</select>
Nested Results for Collection
关联查询
<resultMap id="blogResult" type="Blog">
<id property="id" column="blog_id" />
<result property="title" column="blog_title"/>
<collection property="posts" ofType="Post">
<id property="id" column="post_id"/>
<result property="subject" column="post_subject"/>
<result property="body" column="post_body"/>
</collection>
</resultMap>
Multiple ResultSets for Collection
多返回值
<resultMap id="blogResult" type="Blog">
<id property="id" column="id" />
<result property="title" column="title"/>
<collection property="posts" ofType="Post" resultSet="posts" column="id" foreignColumn="blog_id">
<id property="id" column="id"/>
<result property="subject" column="subject"/>
<result property="body" column="body"/>
</collection>
</resultMap>
discriminator
分类器--按指定字段区分查询字段并进行不同继承对象的封装
<resultMap id="vehicleResult" type="Vehicle">
<id property="id" column="id" />
<result property="vin" column="vin"/>
<result property="year" column="year"/>
<result property="make" column="make"/>
<result property="model" column="model"/>
<result property="color" column="color"/>
<discriminator javaType="int" column="vehicle_type">
<case value="1" resultMap="carResult"/>
<case value="2" resultMap="truckResult"/>
<case value="3" resultMap="vanResult"/>
<case value="4" resultMap="suvResult"/>
</discriminator>
</resultMap>
<!-- extends 可加载父记录字段 -->
<resultMap id="carResult" type="Car" extends="vehicleResult">
<result property="doorCount" column="door_count" />
</resultMap>
Auto-mapping
未手动配置映射关系的,将按照数据库下划线解析成Java驼峰式名称进行自动匹配映射(mapUnderscoreToCamelCase)
匹配模式,默认PARTIAL,FULL有风险,不建议使用,最好手动指定
-
NONE
- disables auto-mapping. Only manually mapped properties will be set. -
PARTIAL
- will auto-map results except those that have nested result mappings defined inside (joins). -
FULL
- auto-maps everything.
可针对单一resultMap设置关闭自动映射
<resultMap id="userResultMap" type="User" autoMapping="false">
<result property="password" column="hashed_password"/>
</resultMap>
cache
查询缓存,mabatis支持 一级缓存(sesson级别,默认开启),以及二级缓存
<!-- 开启二级缓存 -->
<cache/>
- All results from select statements in the mapped statement file will be cached. 查询都将被缓存
- All insert, update and delete statements in the mapped statement file will flush the cache. 更新将删除缓存
- The cache will use a Least Recently Used (LRU) algorithm for eviction. 使用最少使用策略剔除缓存
- The cache will not flush on any sort of time based schedule (i.e. no Flush Interval). 没有定时任务会清除缓存
- The cache will store 1024 references to lists or objects (whatever the query method returns). 最多维持1024个结果
- The cache will be treated as a read/write cache, meaning objects retrieved are not shared and can be safely modified by the caller, without interfering with other potential modifications by other callers or threads. 缓存可读写
缓存绑定对应配置的命名空间上,仅支持xml配置,如果需要进行Java注解支持,需标注 @CacheNamespaceRef
<cache
eviction="FIFO"
flushInterval="60000"
size="512"
readOnly="true"/>
清除算法支持
-
LRU
– Least Recently Used: Removes objects that haven't been used for the longst period of time. -
FIFO
– First In First Out: Removes objects in the order that they entered the cache. -
SOFT
– Soft Reference: Removes objects based on the garbage collector state and the rules of Soft References. -
WEAK
– Weak Reference: More aggressively removes objects based on the garbage collector state and rules of Weak References.
Using a Custom Cache
<cache type="com.domain.something.MyCustomCache"/>
实现Cache接口,并加载执行缓存实现
public interface Cache {
String getId();
int getSize();
void putObject(Object key, Object value);
Object getObject(Object key);
boolean hasKey(Object key);
Object removeObject(Object key);
void clear();
}
cache-ref
复用其他命名空间的缓存配置
Dynamic SQL
mybatis强大的动态SQL支持,通过动态标签进行支持
if
条件选择,不支持elseif表达式
<if test="ognl express return boolean">
SQL expression
</if>
choose, when, otherwise
条件选择,选择满足条件之一进行执行 类似 Java中的 swtich表达式
<choose>
<when test="condtion1">
SQL 1
</when>
<when test="condition2">
SQL 2
</when>
<!-- else 其他情况默认走 otherwise -->
<otherwise>
SQL 3
</otherwise>
</choose>
trim, where, set
Where 动态添加去除多余 and | or 关键字
<where>
dynamic sql
</where>
等同于,不过 trim 更加强大
<trim prefix="WHERE" prefixOverrides="AND |OR ">
...
</trim>
set 更新语句 动态去除多余 , 号
<set>
condition express
</set>
等同于
<trim prefix="SET" suffixOverrides=",">
...
</trim>
foreach
遍历列表迭代器,支持列表( index:索引, item : value )和字典 (index : key , item : value)
<foreach item="item" index="index" collection="list" open="(" separator="," close=")">
#{item}
</foreach>
script
支持Java注解内写动态SQL脚本
bind
支持变量绑定
<bind name=" variable name " value=" ognl expression " />
Multi-db vendor support
支持不同db的变量传递 (_databaseId)
Pluggable Scripting Languages For Dynamic SQL
自定义自己的解析器
public interface LanguageDriver {
ParameterHandler createParameterHandler(MappedStatement mappedStatement, Object parameterObject, BoundSql boundSql);
SqlSource createSqlSource(Configuration configuration, XNode script, Class<?> parameterType);
SqlSource createSqlSource(Configuration configuration, String script, Class<?> parameterType);
}
配置,修改默认脚本语言,会替换mybatis默认的脚本解析支持
<typeAliases>
<typeAlias type="org.sample.MyLanguageDriver" alias="myLanguage"/>
</typeAliases>
<settings>
<setting name="defaultScriptingLanguage" value="myLanguage"/>
</settings>
可指定语句进行支持
<select id="selectBlog" lang="myLanguage">
SELECT * FROM BLOG
</select>
或者Java注解支持
public interface Mapper {
@Lang(MyLanguageDriver.class)
@Select("SELECT * FROM BLOG")
List<Blog> selectBlog();
}