版本说明
jdk:1.8.0_131 springboot:2.1.6.RELEAS maven:3.6.1 database:mysql-5.7.1 mybatis:3.5.2 lombok插件
概述
基于官方文档的学习笔记。项目基于maven构建,项目主要介绍mybatis的使用,因此基本不使用Spring的相关代码
建表语句如下,建表语句来自git-mybatis-3,针对mysql进行部分修改
1 | -- create your own database |
pom 文件
1 |
|
mybatis配置文件
1 |
|
properties
定义配置文件地址,标签属性值可以${xxx}取配置文件的值
DataSource
dataSource标签用来定义一个标准的DataSource标准,mybatis内置了三种类型的DataSource
type="[UNPOOLED|POOLED|JNDI]"
UNPOOLED
每一次数据操作都新建。可做如下配置
driver
url>username
password
defaultTransactionIsolationLevel:数据库隔离级别
defaultNetworkTimeout同时可以为driver设置属性driver.encoding=UTF8
POOLED
使用连接池来管理数据源,除了UNPOOLED的配置还可做如下配置
poolMaximumActiveConnections
poolMaximumIdleConnections
poolMaximumCheckoutTime
poolTimeToWait
poolMaximumLocalBadConnectionTolerance
poolPingQuery
poolPingEnabled
poolPingConnectionsNotUsedFor
JNDI
initial_context data_source
env.前缀的配置将被加载到InitialContext中 env.encoding=UTF8
1 | <dataSource type="JNDI"> |
自定义类型
type可指定为其他工厂类
1 | <dataSource type="org.myproject.C3P0DataSourceFactory"> |
env.encoding=UTF8
mappers
定位映射的SQL语句
1 | <mappers> |
typeAliases
mybatis默认别名有如下
| 别名 | class 类型 |
|---|---|
| _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 |
可指定其他别名
1 | <typeAliases> |
别名可供resultType或parameterType使用
typeHandlers
每当 MyBatis 在 PreparedStatement 上设置参数或从 ResultSet 中检索值时,都会使用 TypeHandler 以适合 Java 类型的方式检索值。 下表描述了默认的 TypeHandlers。
| 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 |
你可以通过继承org.apache.ibatis.type.TypeHandler或者使用org.apache.ibatis.type.BaseTypeHandler来使用非标准的TypeHandler
在配置文件typeHandlers中的typeHandler标签中配置jdbcType,可指定sql表字段类型,若实际java类注解了@MappedJdbcTypes,会无视配置文件
在配置文件typeHandlers中的typeHandler标签中配置javaType,可指定javaBean类型,若实际java类注解了@MappedTypes,会无视配置文件
示例如下:
1 | package org.mybatis.example; |
在mybatis配置文件中若配置了<typehandlers>将会替换默认的数据库类型为VARCHAR,java类型为java.lang.String的转换处理器
1 | <typeHandlers> |
上述配置实际上是调用 org.mybatis.spring.SqlSessionFactoryBean:setTypeHandlers 方法
也可临时指定
1 | <resultMap id="blogMap" type="blog"> |
可使用泛型,通过配置文件typeHandler的javaType觉得处理的java类型
1 | public class GenericTypeHandler<E extends MyObject> extends BaseTypeHandler<E> { |
1 | <typeHandlers> |
plugins
mybatis可定义插件来对数据库操作的各个阶段以切面的方式进行处理。mybatis提供了四种类型的插件
在mybatis中增加配置,<property>的值注入到具体插件的setProperties方法的参数
1 | <plugins> |
插件需要继承org.apache.ibatis.plugin.Interceptor,其中注解Intercepts的值,表示切面的位置
type
Executor(update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)
ParameterHandler(getParameterObject, setParameters)
ResultSetHandler(handleResultSets, handleOutputParameters)
StatementHandler(prepare, parameterize, batch, update, query)
method
type里的方法名
args
type里的方法的参数类型
metdho和args可以定位到一个具体的java方法。所以method和args的值参考type中的方法即可
1 | package org.mybatis.example; |
通过自定义插件我们可以去分析下 #{},${}的区别
1 | ({ |
1 | sqlSession.selectOne( |
#{},${}的实际输出,后者有被sql注入的可能性
1 | boundSql:select * |
1 | boundSql:select * |
transactionManager
略,一般由spring去控制
environments
可配置多环境的数据源
1 | <environments default="development"> |
可指定id的数据源,若未指定则使用default的数据源
1 | SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environment); |
mapping xml
详细信息科参考官方文档 mybatis的核心在于映射的SQL
SELECT
1 | <select id="selectBlog" parameterType="int" resultType="hashmap" > |
#{id}这个通知mybatis创建一个PreparedStatement参数,在预编译阶段实际sql语句会被替换为
select * from Blog where id = ?
实际执行代码类型如下
1 | String selectPerson = "SELECT * FROM PERSON WHERE ID=?"; |
id SQL映射唯一标识
parameterType 请求参数class类型
resultType 返回结果集类型
resultMap 扩展的返回类型的id
flushCache 是否清空二级缓存,默认不清空
useCache 是否开启二级缓存,默认不缓存
timeout 请求超时时间
fetchSize 返回最大条数,默认不限制
statementType 可选STATEMENT,PREPARED或CALLABLE,决定使用的是 Statement,PreparedStatement或CallableStatement,默认的是PREPARED
resultSetType
databaseId databaseIdProvider 多种数据库引擎支持
resultOrdered
resultSets
insert, update and delete
id SQL映射唯一标识
parameterType 请求参数class类型
flushCache 是否清空二级缓存,默认不清空
timeout 请求超时时间
statementType 可选STATEMENT,PREPARED或CALLABLE,决定使用的是 Statement,PreparedStatement或CallableStatement,默认的是PREPARED
useGeneratedKeys 是否使用数据库自增主键
keyProperty 用于指定传入的java成员变量
keyColumn 用于指定数据库表的主键字段
databaseId databaseIdProvider 多种数据库引擎支持
返回主键
在配置了useGeneratedKeys时,如何取得返回的主键
1 | <insert id="insertBlog" useGeneratedKeys="true" keyProperty="java_id" keyColumn="id"> |
1 | SqlSession sqlSession = sqlSessionFactory.openSession(); |
{title=title3, author_id=102, java_id=6}
可以看到返回主键写入到请求的pojo中了
mybatis还提供了其他方式进行主键的生成
<selectKey> keyProperty 指定存储主键的字段 keyColumn 用于指定数据库表的主键字段
order Before或者After,若是Before,则先生成主键,执行insert。而设置为After,则先insert,再讲返回的主键插入的写入请求的pojo中
resultType 返回主键类型
statementType 可选STATEMENT,PREPARED或CALLABLE,决定使用的是 Statement,PreparedStatement或CallableStatement,默认的是PREPARED
批量插入
1 | <insert id="insertBlog" useGeneratedKeys="true" keyProperty="id"> |
SQL
可被其他SQL映射语句重复使用
1 | <sql id="userColumns"> ${alias}.id,${alias}.username,${alias}.password </sql> |
Parameters
${}或#{}
${}会被直接替换为值,而#{}则进入prepared阶段
使用介绍
1 | ("select * from user where ${column} = #{value}") |
#{}高阶
可以指定某个属性使用独立的处理器,该处理器可以不用注册,但是需要使用全名,如果使用简称则需要已经注册的
#{age,javaType=int,jdbcType=NUMERIC,typeHandler=MyTypeHandler}
指定double的精度
#{height,javaType=double,jdbcType=NUMERIC,numericScale=2}
ResultMap
通过自定义映射关系来处理复杂的返回结果集
属性 id 主键 type 返回class类型 autoMapping 自动匹配的模式。查询的ResultSet转换pojo时,会自动查找同名属性(忽略大小写)
NONE表示不启用自动映射PARTIAL表示只对非嵌套的 resultMap 进行自动映射FULL表示对所有的 resultMap 都进行自动映射
1 | <resultMap id="detailedBlogResultMap" type="Blog"> |
id & result
映射基本类型,id表示主键
propertypojo成员变量
column数据库字段
javaType成员变量class类型
jdbcType数据库字段类型
typeHandler使用具体的处理器去处理
支持的数据库类型
BITFLOATCHARTIMESTAMPOTHERUNDEFINED>TINYINTREALVARCHARBINARYBLOBNVARCHAR>SMALLINTDOUBLELONGVARCHARVARBINARYCLOBNCHAR>INTEGERNUMERICDATELONGVARBINARYBOOLEANNCLOB>BIGINTDECIMALTIMENULLCURSORARRAY
constructor
为type有参构造器传递参数,分为<idArg>(主键)和<arg>,默认构造器参数根据顺序进行传参。
propertypojo成员变量
column数据库字段
javaType成员变量class类型
jdbcType数据库字段类型
typeHandler使用具体的处理器去处理select其他映射语句的 id,根据其查询值注入构造器参数中resultMap引入其他resultMap>name根据名称指定具体参数值,无视参数顺序。
association
一定要注意集合类型的长度
propertypojo成员变量
column数据库字段
javaType成员变量class类型
jdbcType数据库字段类型
typeHandler使用具体的处理器去处理select其他映射语句的 id,根据其查询值注入到成员变量中resultMap引入其他resultMap>fetchType可设置为lazy或eager是否延迟加载columnPrefix当涉及到多表查询时,多表的字段相同,那么sql语句就需要使用as来区分字段。 例如:
1 | <select id="selectBlog" resultMap="blogResult"> |
一般情况下我们
1 | <resultMap id="blogResult" type="Blog"> |
我们可以使用columnPrefix来处理
1 | <resultMap id="blogResult" type="Blog"> |
discriminator
1 | <resultMap id="vehicleResult" type="Vehicle"> |
根据column的值决定哪种<case>执行
cache
略过,由spring去控制
Dynamic SQL
SpringBoot
maven 依赖
1 | <dependency> |
可在springboot配置文件application.properties(或application.yml).中配置Mybatis使用mybatis前缀作为配置
config-location mybatis配置文件目录 mapper-locations mapper文件目录地址 type-aliases-package 别名包名,不同目录可用,; \t\n分割 type-handlers-package 类型转换器包名,不同目录可用,; \t\n分割 configuration-properties 指定properties配置文件,可被mybatis配置文件和mapper文件中作为占位符使用 configuration.* 等同于mybatis配置文件中的settings
可使用ConfigurationCustomizer来自定制细节
1 |
|
mybatis会自动检测继承mybatis接口的bean
Interceptor
TypeHandler
LanguageDriver (Requires to use together with mybatis-spring 2.0.2+)
DatabaseIdProvider
1 |
|