动静SQL
if
依据条件蕴含where子句的一部分
<select id="findActiveBlogLike" resultType="Blog"> SELECT * FROM BLOG WHERE state = 'ACTIVE' <where> <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></select>
紧接着 < where > 的第一个条件不要加AND
choose-when-otherwise
不应用所有的条件,只是想从多个条件中抉择一个应用
<select id="findActiveBlogLike" resultType="Blog"> SELECT * FROM BLOG WHERE state = 'ACTIVE' <choose> <when tset="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></select>
where
- where元素只会在子元素返回内容的状况下才会插入WHRER的子语句
若子语句的结尾为AND或者OR,where元素会将这些去除
<select id="findActiveBlogLike" resultType="Blog"> SELECT * FROM BLOG <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></select>
trim
能够通过自定义trim元素来定制where元素的性能
比方和where元素等价的自定义trim元素.会移除所有prefixOverrides属性中指定的内容,并且插入prefix属性中指定的内容:
<trim prefix="WHERE" prefixOverrides="AND |OR"> ...</trim>
prefixOverrides属性会疏忽通过管道符宰割的文本序列 ,不同的文本序列之间必须要有空格.
- 和set元素等价的自定义trim元素. 笼罩了后缀值设置,并且自定义前缀值:
<trim prefix="SET" suffixOverrides=","> ...</trim>
set
- 用于动静更新语句的叫作set
set元素能够用于动静蕴含须要更新的列,疏忽不更新的列
<update id="updateAuthorIfNecessary"> 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> where id = #{id}</update>
set元素会动静地进行行首插入SET关键字,并会删掉额定的逗号,这些逗号是在应用条件语句给列赋值时引入的
foreach
对汇合进行遍历的时候应用foreach, 特地是在构建IN条件语句的时候
<select id="selectPostIn" resultType="domain.blog.Post"> SELECT * FROM POST p WHERE ID IN <foreach item="item" index="index" collection="list" open="(" separator="," close=")"> #{item} </foreach> </select>
foreach容许指定一个汇合:
- 申明能够在元素体内应用的汇合项item和索引index变量
- 指定结尾open与结尾close的字符串以及汇合项迭代之间的分隔符separator
- foreach不会谬误地增加多余的分隔符
应用foreach时:
- 能够将任何可迭代对象,比方List,Set,Map对象或者数组对象作为汇合参数传递给foreach
当应用可迭代对象或者数组时:
- index是以后迭代的序号
- item的值是本次迭代获取到的元素
当应用Map对象或者Map.Entry对象的汇合
- index是键
item是值
script
要是想要在带注解的接口类中应用动静SQL语句,能够应用script元素
@update({"<script>", "update Author", "<set>", "<if test='username != null'>username=#{username},</if>", "<if test='password != null'>password=#{password},</if>", "<if test='email != null'>email=#{email},</if>", "</set>", "where id=#{id}", "</script>"}) })void updateAuthorValues(Author author);
bind
能够应用bind元素在OGNL表达式以外创立一个变量,并绑定到上下文中
<select id="selectBlogsLike" resultType="Blog"> <bind name="pattern" value="'%' + _parameter.getTitle() + '%'" /> SELECT * FROM BLOG WHERE title LIKE #{pattern}</select>
多数据库反对
如果配置了databaseIdProvider, 就能够在动静代码中应用名为 "_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>
动静SQL中插入脚本语言
- MyBatis 3.2版本开始反对插入脚本语言
- 容许插入一种语言驱动,并基于这种语言来编写动静SQL查问语句
通过实现LanguageDriver接口插入语言:
public interface LanguageDriver { ParameterHandler createParameterHandler(MappedStatement mappedStatement, Object parameterObject, BoundSql boundSql); SqlSource createSqlSource(Configuration configuration, XNode script, Class<?> parameterType); SqlSource crateSqlSource(Configuration configuration, String script, Class<?> parameterType);}
实现自定义语言驱动后,能够在mybatis-config.xml文件中设置为默认语言:
<typeAliases> <typeAliase type="com.oxford.MyLanguageDriver" alias="myLanguage" /></typeAliases><settings> <setting name="defaultScriptingLanguage" value="myLanguage" /></settings>
也能够应用lang属性为特定的语句指定语言:
<select id="selectBlog" lang="myLanguage"> SELECT * FROM BLOG</select>
或者在mapper接口上应用 @Lang注解:
public interface Mapper { @Lang(MyLanguageDriver.class) @Select("SELECT * FROM BLOG") List<Blog> selectBlog();}
MyBatis中的xml文件中的所有xml标签都由默认MyBatis语言提供,是由语言驱动org.apache.ibatis.scripting.xmltags.XmlLanguageDriver, 别名为xml. 提供的.
Java API
MyBatis的执行办法在SqlSession类中
语句执行办法
这些办法被用来执行定义在SQL映射XML文件中的SELECT,INSERT,UPDATE和DELETE语句
- 每一个办法都接管语句的ID以及参数对象
参数能够是原始类型(反对主动装箱),包装类,JavaBean,POJO或者Map
selectOne
<T> T selectOne(String statement, Object parameter);
selectList
<E> List<E> selectList(String statement, Object parameter);
selectOne和selectList的不同点是:
- selectOne必须返回一个对象或者null值, 如果返回值多于一个就会抛出异样
如果不分明返回对象会有多少个,就应用selectList
selectCursor
<T> Cursor<T> selectCursor(String statement, Object parameter);
游标Cursor与列表List返回的后果雷同,不同的是: 游标借助迭代器实现了数据的惰性加载
try (Cursor<Entity> entities = session.selectCursor(statement, param)) { for (Entity entity : entities) { // 解决单个实体 }}
selectMap
<K,V> Map<K,V> selectMap(String statement, Object parameter, String mapKey);
selectMap会将返回对象的其中一个属性作为key值,将对象作为value值,从而将多个后果集转为Map类型值
insert
int insert(String statement, Object parameter);
update
int update(String statement, Object parameter);
delete
int delete(String statement, Obejct parameter);
- 如果须要查看某个对象是否存在, 最好的方法就是查问一个count值,应用0或者1
- 因为不是所有语句都须要参数,所以这些办法都具备一个不须要参数的重载模式
insert, update 和delete办法返回值示意受该语句影响的行数
select高级版本
- 容许限度返回行数的范畴
- 提供自定义后果解决逻辑
通常是在数据集十分宏大的情景下应用
selectList
<E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds);
selectCursor
<T> List<T> selectCursor(String statement, Object parameter, RowBounds rowBounds);
selectMap
<K, V> Map<K,V> selectMap(String statement, Object parameter, String mapKey, RowBounds rowBounds);
select
void select(String statement, Object parameter, ResultHandler<T> handler);
select
void select(String statement Object parameter, RowBounds rowBounds, ResultHandler<T> handler);
RowBounds参数:
- 指定MyBatis略过指定数量的记录,并限度返回后果的数量
RowBounds类的offset和limit值只有在构造函数时能力传入,其余时候是不能批改的
int offset = 100;int limit = 25;RowBounds rowBounds = new RowBounds(offset, limit);
ResultHandler参数:
- 容许自定义每行后果的处理过程
- 能够增加到List中,创立Map和Set. 甚至抛弃每个返回值,只保留计算后的统计后果
ResultHandler接口:
package org.apache.ibatis.session;public interface ResultHandler<T> { void handlerResult(ResultContext<? extends T> context);}
ResultContext参数:
- 容许拜访后果对象和以后已被创立的对象数目
- 提供一个返回值为Boolean的stop办法,能够应用这个stop办法来进行MyBatis加载更多的后果
应用ResultHandler要留神两条限度:
- 应用带ResultHandler参数的办法时,收到的数据不会被缓存
当应用高级的后果映射集resultMap时 ,MyBatis很可能须要数行后果来结构一个对象.如果这时应用了ResultHandler, 可能会接管到关联association或者汇合collection中尚未被残缺填充的对象
革除批量更新办法
当ExecutorType设置为ExecutorType.BATCH时,能够应用flushStatements革除缓存在JDBC驱动类中的批量更新语句
flushStatements
List<BatchResult> flushStatements();
事务管制办法
- 管制事务作用域的办法有四个,如果曾经设置了主动提交或者应用了内部事务管理器, 就不须要应用这些办法
如果正在应用Connection实例管制的JDBC事务管理器,就能够应用以下的四个办法:
void commit();void commit(boolean force);void rollback();void rollback(boolean force);
- 默认状况下 ,MyBatis不会主动提交事务,除非发现到调用了插入,更新或删除办法扭转了数据库
如果没有应用这些办法提交批改,那么就能够在commit和rollback办法参数传入true值来保障事务被失常提交
- 留神: 在主动提交模式或者应用了内部事务管理器的状况下,设置force值对session有效
- 大部分状况下,无需调用rollback(), 因为MyBatis会在没有调用commit() 时实现回滚操作
- 然而,当要在一个可能屡次提交或回滚的session中具体管制事务,就要应用到回滚rollback操作