动态SQL
if
SELECT * FROM BLOG WHERE state = 'ACTIVE'
AND title like #{title}
AND author_name like #{author.name}
紧接着 < where > 的第一个条件不要加AND
choose-when-otherwise
SELECT * FROM BLOG WHERE state = 'ACTIVE'
AND title like #{title}
AND author_name like #{author.name}
AND featured = 1
where
where 元素只会在子元素返回内容的情况下才会插入WHRER 的子语句
若子语句的开头为AND 或者OR,where 元素会将这些去除
SELECT * FROM BLOG
state = #{state}
AND title like #{title}
AND author_name like #{author.name}
trim
可以通过自定义trim 元素来定制where 元素的功能
比如和where 元素等价的自定义trim 元素.会移除所有prefixOverrides 属性中指定的内容,并且插入prefix 属性中指定的内容:
...
prefixOverrides 属性会忽略通过管道符分割的文本序列 ,不同的文本序列之间必须要有空格.
和set 元素等价的自定义trim元素. 覆盖了后缀值设置,并且自定义前缀值:
...
set
用于动态更新语句的叫作set
set 元素可以用于动态包含需要更新的列,忽略不更新的列
update Author
username = #{username},
password = #{password},
email = #{email},
bio = #{bio}
where id = #{id}
set 元素会动态地进行行首插入SET 关键字,并会删掉额外的逗号,这些逗号是在使用条件语句给列赋值时引入的
foreach
对集合进行遍历的时候使用foreach, 特别是在构建IN 条件语句的时候
SELECT *
FROM POST p
WHERE ID IN
#{item}
foreach允许指定一个集合:
声明可以在元素体内使用的集合项item 和索引index 变量
指定开头open 与结尾close 的字符串以及集合项迭代之间的分隔符separator
foreach不会错误地添加多余的分隔符
使用foreach时:
可以将任何可迭代对象,比如List,Set,Map对象或者数组对象 作为集合参数传递给foreach
当使用可迭代对象 或者数组 时:
index 是当前迭代的序号
item 的值是本次迭代获取到的元素
当使用Map 对象或者Map.Entry 对象的集合
script
要是想要在带注解的接口类中使用动态SQL语句,可以使用script 元素
@update({""})
})
void updateAuthorValues(Author author);
bind
可以使用bind 元素在OGNL表达式以外创建一个变量,并绑定到上下文中
SELECT * FROM BLOG
WHERE title LIKE #{pattern}
多数据库支持
如果配置了databaseIdProvider, 就可以在动态代码中使用名为 "_databaseId" 的变量来为不同的数据库构建特定的语句
select seq_users.nextval from dual
select nextval for seq_users from sysibm.sysdummy1
insert into users values (#{id}, #{name})
动态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 文件中设置为默认语言:
SELECT * FROM BLOG
public interface Mapper {
@Lang(MyLanguageDriver.class)
@Select("SELECT * FROM BLOG")
List 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 selectOne(String statement, Object parameter);
selectList
List selectList(String statement, Object parameter);
selectOne和selectList的不同点是:
selectOne 必须返回一个对象或者null值, 如果返回值多于一个就会抛出异常
如果不清楚返回对象会有多少个,就使用selectList
selectCursor
Cursor selectCursor(String statement, Object parameter);
游标Cursor 与列表List 返回的结果相同,不同的是: 游标借助迭代器 实现了数据的惰性加载
try (Cursor entities = session.selectCursor(statement, param)) {
for (Entity entity : entities) {
// 处理单个实体
}
}
selectMap
Map 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
List selectList(String statement, Object parameter, RowBounds rowBounds);
selectCursor
List selectCursor(String statement, Object parameter, RowBounds rowBounds);
selectMap
Map selectMap(String statement, Object parameter, String mapKey, RowBounds rowBounds);
select
void select(String statement, Object parameter, ResultHandler handler);
select
void select(String statement Object parameter, RowBounds rowBounds, ResultHandler handler);
package org.apache.ibatis.session;
public interface ResultHandler {
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 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 操作