文章目录
官方文档
核心类:SqlSessionFactory/SqlSessionFactoryBuilder、SqlSession、mappers
Getting Started
SqlSessionFactory配置要素:DataSource、TransactionFactory、mappers
Building SqlSessionFactory from XML
Resource resource = Resources.getResourceAsStream(xmlPath);
SqlSessionFactory ssf = new SqlSessionFactoryBuilder().build(resource);
Building SqlSessionFactory without XML
Environment environment = new Environment(id, transactionFactory, datasource);
Configuration configuration = new Configuration(environment);
configuration.addMapper();//加载mapper
SqlSessionFactory ssf = new SqlSessionFactoryBuilder().build(configuration);
Acquiring a SqlSession from SqlSessionFactory
SqlSession ss = ssf.openSession();
//id执行
ss.selectOne(id, params);
//接口执行
BlogMapper bm = ss.getMapper(BlogMapper.class);
bm.selectBlog();//调用接口方法执行查询
Exploring Mapped SQL Statement
XML方式、Annotation方式。
注解:@Insert、@DELETE、@SELECT、@Update、@Results+@Result
Scope and Lifecycle
SqlSessionFactory;application级
SqlSessionFactoryBuilder、SqlSession、Mapper;一般method级别
Configuration XML
peoperties
resource引入外部配置文件,定义公用变量;通过${}引用。。
<properties resource="org/mybatis/example/config.properties">
<property name="ltl" value="lkk"/>
</properties>
或在java代码中通过重载的SqlSessionFactoryBuilder#build()引入。
优先级:build形参、resource引入的配置文件、<property>标签。
settings
调整设置,修改mybatis运行时行为。
<settings>
<setting name="cacheEnabled" value="true"/>
</settings>
typeAliases
类型别名;减少类全限定名的冗余。package导入默认@Alias注解、或首字母小写。
<typeAliases>
<typeAlias alias="Author" type="domain.blog.Author"/>
<package name="domain.blog"/>
</typeAliases>
内建类型别名,全小写:
- _int、_byte等基本类型
- integer、string、map、hashmap、list等对象类型
typeHandlers
类型处理器;java参数–数据库类型、结果集字段–java类型映射。
package扫描包下BaseTypeHandler子类。
<typeHandlers>
<typeHandler handler="org.mybatis.example.ExampleTypeHandler"/>
<package name="org.mybatis.example"/>
</typeHandlers>
Handling Enums
EnumTypeHandler,解析为枚举类;
EnumOrdinalTypeHandler,解析为值。默认。
<resultMap type="lkk" id="lkk">
<result column="roundingMode" property="roundingMode"/>
<result column="roundingMode" property="roundingMode"
typeHandler="org.apache.ibatis.type.EnumTypeHandler"/>
</resultMap>
objectFactory
对象工厂;映射结果集–java对象。
使用默认构造器、带参构造器实例化对象。
plugins
插件;拦截器,嵌入自定义逻辑。
可拦截方法:
Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)
ParameterHandler (getParameterObject, setParameters)
ResultSetHandler (handleResultSets, handleOutputParameters)
StatementHandler (prepare, parameterize, batch, update, query)
实现拦截器:
@Intercepts({@Signature(type= Executor.class, method = "update",
args = {MappedStatement.class,Object.class})})
public class ExamplePlugin implements Interceptor {
//TODO 实现Interceptor
}
配置文件加入拦截器:
<plugins>
<plugin interceptor="org.mybatis.example.ExamplePlugin">
<property name="someProperty" value="100"/>
</plugin>
</plugins>
java加入拦截器,配置bean即可。
environments
环境;datasource+transactionManager
Environment environment = new Environment(id, transactionFactory, datasource);
datasource类型:POOLED、UNPOOLED、JNDI
transactionManager类型:JDBC、MANAGED(jta)
databaseIdProvider
数据库厂商标识;多数据库支持,根据不同的数据库厂商标识,执行不同的语句。
<databaseIdProvider>、mapper中的databaseId属性。优先使用databaseId匹配的sql语句。
默认配置:<databaseIdProvider type=“DB_VENDOR”/>,实现类VendorDatabaseIdProvider,返回databaseId为DatabaseMetaData#getProductName()。
配置别名:
<databaseIdProvider type="DB_VENDOR">
<property key="Oracle" value="oracle"/>
<property key="DB2" value="db2" />
</databaseIdProvider>
自定义databaseIdProvider,实现org.apache.ibatis.mapping.DatabaseIdProvider
mappers
映射器;sql映射语句;xml、java类。
<mappers>
<mapper resource="org/mybatis/builder/AuthorMapper.xml"/>
<mapper url="file:///var/mappers/BlogMapper.xml"/>
<mapper class="org.mybatis.builder.AuthorMapper"/>
<package name="org.mybatis.builder"/>
</mappers>
Mapper XML Files
官网mapper
顶级元素:cache、cache-ref、resultMap、sql、insert/update/delete/select
select
属性,无默认值则为unset,依赖driver设置:
- id;命名空间中唯一的标识符
- parameterType;参数类型
- resultType、resultMap;返回类型
- flushCache;清空本地缓存和二级缓存,默认false
- useCache;使用二级缓存,默认true
- timeout;超时时间,单位s
- fetchSize;批量返回数
- statementType;statement类型,值:STATEMENT、PREPARED(默认)、CALLABLE;
- resultSetType;ResultSet遍历方式,值:FORWARD_ONLY、SCROLL_SENSITIVE、SCROLL_INSENSITIVE、DEFAULT
- databaseId;数据库id,用于支持多数据库类型
- resultOrdered、resultSets
insert、update、delete
特殊属性
- flushCache;默认为true
- useGeneratedKeys;使用JDBC#getGeneratedKeys()获取数据库生成的主键,默认false
- keyProperty;主键,通过JDBC#getGeneratedKeys()、或selectKey子元素获得值。
selectKey子元素
数据库不支持自动生成主键时使用,属性:
- keyProperty;需被设置的目标属性
- resultType;结果类型
- order;生成主键、插入语句顺序,BEFORE、AFTER;
例:
数据库支持自动生成主键
<insert id="insertAuthor" useGeneratedKeys="true" keyProperty="id">
insert into Author (username,password,email,bio)
values (#{username},#{password},#{email},#{bio})
</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>
sql
定义可重用的sql代码段,可使用${}占位符。
通过<include refid="id>属性引用,<property>标签传值。sql中可引用另一个sql标签。
例:
<sql id="userColumns">${alias}.id,${alias}.username</sql>
<select id="selectUser">
select <include refid="userColumns"><property name="alias" value="t1"/></include>
from user t1
</select>
Parameters
parameterType;标签设置参数类型。<select id=“lkk” parameterType=“String” />
jdbcType;变量设置参数类型。#{property,javaType=int,jdbcType=NUMERIC}
如果一个列允许null值,且可能传递值null;必须指定jdbcType。
内置参数:_parameter、_databaseId
参数解析
https://blog.csdn.net/cccmercy/article/details/83211561
https://blog.csdn.net/zjl_csdn/article/details/88854073
单个参数
参数为POJO、Map,按属性名、键取参数值,通过getter实现。
参数为集合、数组,通过collection、list、array取参数值
多个参数
通过@Param设置参数名
paramN、argN、N取参数值。N从0开始。
占位符
占位符:#{}、${}
使用${}时,建议检验字符串,防止sql注入。
Result Maps
select#resultType、resultMap属性;resultMap标签。
resultMap属性:
- id;resultMap唯一标记
- type;java类全名,或别名。
- autoMapping;自动映射。unset默。
- id;主键,id、column。标记结果集,便于全局调用
- result;数据映射,property、column。
- constructor;java类没有无参构造器时使用。
- association;一对一
- collection;一对多
- discriminator;鉴别器级联
例:
<resultMap id="userResultMap" type="User">
<id property="id" column="user_id" />
<result property="username" column="user_name"/>
<result property="password" column="hashed_password"/>
</resultMap>
constructor
没有无参构造器时使用,子元素顺序与构造器形参列表一致。
子元素:<idArg>、<arg>
子元素属性:column、name(构造器形参名)、javaType等。
<resultMap id="userResultMap" type="User">
<constructor>
<idArg column="id" javaType="int"/>
<arg column="username" javaType="String"/>
<arg column="age" javaType="_int"/>
</constructor>
</resultMap>
association
一对一关联;构建对象。
实现:嵌套select查询(select属性)、嵌套结果映射(id、property子元素,或resultMap属性)。
嵌套select查询
属性:column(传递给sql的参数)、property、javaType、select、fetchType(eager、lazy)
传递复合主键:column=“{prop1=col1,prop2=col2}”;prop1、prop2为参数对象
会有N+1问题,每个关联都会有一次sql查询。
<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>
嵌套结果查询
属性:resultMap、columnPrefix(resultMap column增加前缀,以便复用)、notNullColumn
子元素:<id>、<property>
<resultMap id="blogResult" type="Blog">
<id property="id" column="blog_id" />
<result property="title" column="blog_title"/>
<association property="author" resultMap="authorResult" />
<association property="coAuthor" resultMap="authorResult" columnPrefix="co_" />
</resultMap>
多结果集
属性:property、column、foreignColumn、resultSet
通过存储过程实现结果映射。
collection
一对多映射;类似association。
额外属性ofType,标识collection的元素类型;必需。其他与association一致。
嵌套查询:
<collection property="posts" column="id" ofType="Post" select="selectPostsForBlog"/>
嵌套结果
<resultMap id="blogResult" type="Blog">
<id property="id" column="blog_id" />
<result property="title" column="blog_title"/>
<collection property="posts" ofType="Post" resultMap="blogPostResult" columnPrefix="post_"/>
</resultMap>
discriminator
鉴别器;条件化装配。类似switch。
属性:column、javaType;子元素,value、resultMap/resultType
鉴别器返回case条件类型,或鉴别器外类型。case类型继承鉴别器外类型。
<resultMap id="vehicleResult" type="Vehicle">
<discriminator javaType="int" column="draft">
<case value="1" resultMap="carResult"/>
</discriminator>
</resultMap>
<resultMap> extends属性,继承。
<resultMap id="carResult" type="Car" extends="vehicleResult">
<result property="doorCount" column="door_count" />
</resultMap>
auto_mapping
自动映射;自动匹配column、属性,忽略大小写。
手动配置优先。
mapUnderscoreToCamelCase;true设置_分隔转为驼峰命名。
自动映射级别:
- NONE;关闭
- PARTIAL;不自动映射关联类型。默认。
- FULL;全部自动映射。可能导致关联类型映射错误。
<resultMap id="userResultMap" type="User" autoMapping="false">
<result property="password" column="hashed_password"/>
</resultMap>
cache
一级缓存存于session,二级缓存存于sqlSessionFactory。
默认只开启会话缓存,开启二级缓存:<setting name=“cacheEnabled” value=“true”/>
<cache/>,mapper中开启二级缓存。缓存只作用于cache标签所在映射文件;
<cache
eviction="FIFO"
flushInterval="60000"
size="512"
readOnly="true"/>
eviction;缓存清理策略:FIFO、LRU、SOFT(软引用)、WEAK(弱引用)
flushInterval;过期时间,ms
size;缓存引用数量
readOnly;缓存返回的对象只读
不建议使用mybatis的二级缓存,缓存分散;容易导致数据不一致。使用EHCache、redis替代。
Dynamic SQL
官网动态SQL
基于OGNL(Object-Graph Navigation Language)表达式进行运算。
内置参数:_parameter、_databaseId
先替换$,生成模板sql;再填充参数
OGNL表达式
https://blog.csdn.net/isea533/article/details/50061705
逻辑运算:and/&&、or/||、!/not、in、not in
比较运算:==/eq、!=/neq、lt/lte、gt/gte
代数运算:+-*/%
方法运算:e1[e2]、e.method()、e.field、@class@method()、@class@field
OGNL会将’a’解析为字符,“a”、‘a’.toString()解析为字符串。
if
属性:test
<if test="title != null">
AND title like #{title}
</if>
choose、when、otherwise
类似switch语句。
when属性:test
<choose>
<when test="title != null">
AND title like #{title}
</when>
<when test="author != null and author.name != null">
AND author_name like #{author.name}
</when>
<otherwise>
AND featured = 1
</otherwise>
</choose>
trim、where、set
where元素,有sql子句时才插入where子句,自动剔除子句开头的and、or前缀。
<where>
<if test="state != null">
state = #{state}
</if>
<if test="title != null">
AND title like #{title}
</if>
<if test="author != null and author.name != null">
AND author_name like #{author.name}
</if>
</where>
set元素,构建set语句;自动删除无用逗号。
update Author
<set>
<if test="username != null">username=#{username},</if>
<if test="password != null">password=#{password},</if>
<if test="email != null">email=#{email},</if>
<if test="bio != null">bio=#{bio}</if>
</set>
trim元素,定制格式化方式。属性:prefix、prifixOverrides、suffixOverrides
等价于where
<trim prefix="WHERE" prefixOverrides="AND |OR ">
...
</trim>
等价于set
<trim prefix="WHERE" suffixOverrides=", ">
...
</trim>
foreach
属性:item、index、collection、open、seperator、close
index,list、set、array时为索引数值,map为key。
<foreach item="item" index="index" collection="list" open="(" seperator="," close=")">
#{item}
</foreach>
SELECT COUNT(id)
FROM rd_zone_segment_delivery_fee_info
WHERE small_transport_zone_id=#{zoneId}
AND start_addr_type=#{startAddrType}
AND end_addr_type=#{endAddrType}
AND (start_addr, end_addr) IN
<foreach collection="startAddrs" item="startAddr" index="i" open="(" separator="," close=")">
#{startAddr},#{endAddrs[${i}]}
</foreach>
SELECT COUNT(id)
FROM rd_zone_segment_delivery_fee_info
WHERE small_transport_zone_id=#{zoneId}
AND start_addr_type=#{startAddrType}
AND end_addr_type=#{endAddrType}
AND (start_addr, end_addr) IN
<foreach collection="startAddrs" item="startAddr" open="(" separator="," close=")">
<foreach collection="endAddrs" item="endAddr" separator="," >
(#{startAddr},#{endAddr})
</foreach>
</foreach>
bind
从OGNL表达式中创建一个变量,并绑定到上下文。
属性:name、value
<select id="selectUser">
<bind name="pattern" value="'%'+_parameter.name+'%'"/>
select * from users where name like #{pattern}
</select>
Multi-db vendor support
通过_databaseId判定当前数据库类型。
<insert id="insert">
<selectKey keyProperty="id" resultType="int" order="BEFORE">
<if test="_databaseId == 'oracle'">
select seq_users.nextval from dual
</if>
<if test="_databaseId == 'db2'">
select nextval for seq_users from sysibm.sysdummy1"
</if>
</selectKey>
insert into users values (#{id}, #{name})
</insert>
Java API
SqlSessionFactory/SqlSessionFactoryBuilder、SqlSession、mappers
SqlSessionFactoryBuilder
创建SqlSessionFactory,五个重载build()方法。
build(configuration);
build(inputStream);
build(inputStream, env);
build(inputStream, prop);
build(inputStream, env, prop);
Configuration
Environment env = new Environment(id, transactionManager, dataSource);//id无用
Configuration con = new Configuration(env);
Resources,org.apache.ibatis.io包下;mybatis文件加载工具类。
SqlSessionFactory
六个重载getSession()方法,创建SqlSession实例。考虑:
- 事务处理;隔离级别TransactionIsolationLevel、自动提交boolean。默认:驱动默认值、false
- 连接;传入Connection。默认:使用dataSource的连接
- 执行语句;ExecutorType,是否复用sql。默认:不复用。
ExecutorType,枚举类;
- ExecutorType.SIMPLE无特殊处理
- ExecutorType.REUSE复用
- ExecutoryType.BATCH批量执行
SqlSession
执行sql语句。
映射器Mapper
声明与sqlSession方法匹配的接口类。
方法id、返回类型、参数列表需匹配。
映射器注解:
- @CacheNamespace、@CacheNamespaceRef;注解
- @Property;属性值,<property>
- @Insert、@Update、@Delete、@Select、@SelectKey;sql语句
SQL Builder Class
SQL
匿名内部类方式
String sql = new SQL(){{ //第二层{}为初始化块
SELECT("name, age");
FROM("student");
if(age!=null){
WHERE("age = #{age}");//构建sql与xml一致
}
}}.toString();
api方式
String sql = new SQL()
.SELECT("name, age")
.FROM("student")
.toString();
Logging
日志查找顺序:SLF4J、Apache Commons Logging、Log4j2、Log4j、JDK Logging
注意:如果Tomcat类路径中包含Apache Commons Logging,故使用其作为日志。
指定日志类:
<settings>
<setting name="logImpl" value="LOG4J"/>
</settings>
SpringBoot整合mybatis
https://blog.csdn.net/tuesdayma/article/details/81081666
导包:mybatis-spring-boot-starter
配置:SqlSessionFactoryBean
@Bean("firstMybatis")
public SqlSessionFactoryBean first(DataSource dataSource,
@Value("${mybatis.mapper-locations:}")String locs) throws IOException {
SqlSessionFactoryBean sfb = new SqlSessionFactoryBean();
sfb.setDataSource(dataSource);
sfb.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(locs));
return sfb;
}
配置属性:mybatis.*;mybatis.configuration.*,配置Configuration。
mybatis锁,sql中:for update,lock in share mode;https://blog.csdn.net/cug_jiang126com/article/details/50544728
多个mybatis,@MapperScan指定;
默认事务管理器SpringManagedTransactionFactory,使用其他事务管理器,在有事务active时获取sqlSession会报错。
核心点:Configuration、mapper、@MapperScan