动静 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 操作