语句执行方法

这些方法被用来执行定义在 SQL 映射 XML 文件中的 SELECT、INSERT、UPDATE 和 DELETE 语句。你可以通过名字快速了解它们的作用,每一方法都接受语句的 ID 以及参数对象,参数可以是原始类型(支持自动装箱或包装类)、JavaBean、POJO 或 Map。

  1. <T> T selectOne(String statement, Object parameter)
  2. <E> List<E> selectList(String statement, Object parameter)
  3. <T> Cursor<T> selectCursor(String statement, Object parameter)
  4. <K,V> Map<K,V> selectMap(String statement, Object parameter, String mapKey)
  5. int insert(String statement, Object parameter)
  6. int update(String statement, Object parameter)
  7. int delete(String statement, Object parameter)

selectOne 和 selectList 的不同仅仅是 selectOne 必须返回一个对象或 null 值。如果返回值多于一个,就会抛出异常。如果你不知道返回对象会有多少,请使用 selectList。如果需要查看某个对象是否存在,最好的办法是查询一个 count 值(0 或 1)。selectMap 稍微特殊一点,它会将返回对象的其中一个属性作为 key 值,将对象作为 value 值,从而将多个结果集转为 Map 类型值。由于并不是所有语句都需要参数,所以这些方法都具有一个不需要参数的重载形式。

游标(Cursor)与列表(List)返回的结果相同,不同的是,游标借助迭代器实现了数据的惰性加载。

  1. try (Cursor<MyEntity> entities = session.selectCursor(statement, param)) {
  2. for (MyEntity entity:entities) {
  3. // 处理单个实体
  4. }
  5. }

insert、update 以及 delete 方法返回的值表示受该语句影响的行数。

  1. <T> T selectOne(String statement)
  2. <E> List<E> selectList(String statement)
  3. <T> Cursor<T> selectCursor(String statement)
  4. <K,V> Map<K,V> selectMap(String statement, String mapKey)
  5. int insert(String statement)
  6. int update(String statement)
  7. int delete(String statement)

最后,还有 select 方法的三个高级版本,它们允许你限制返回行数的范围,或是提供自定义结果处理逻辑,通常在数据集非常庞大的情形下使用。

  1. <E> List<E> selectList (String statement, Object parameter, RowBounds rowBounds)
  2. <T> Cursor<T> selectCursor(String statement, Object parameter, RowBounds rowBounds)
  3. <K,V> Map<K,V> selectMap(String statement, Object parameter, String mapKey, RowBounds rowbounds)
  4. void select (String statement, Object parameter, ResultHandler<T> handler)
  5. void select (String statement, Object parameter, RowBounds rowBounds, ResultHandler<T> handler)

RowBounds 参数会告诉 MyBatis 略过指定数量的记录,并限制返回结果的数量。RowBounds 类的 offset 和 limit 值只有在构造函数时才能传入,其它时候是不能修改的。

  1. int offset = 100;
  2. int limit = 25;
  3. RowBounds rowBounds = new RowBounds(offset, limit);

数据库驱动决定了略过记录时的查询效率。为了获得最佳的性能,建议将 ResultSet 类型设置为 SCROLL_SENSITIVE 或 SCROLL_INSENSITIVE(换句话说:不要使用 FORWARD_ONLY)。

ResultHandler 参数允许自定义每行结果的处理过程。你可以将它添加到 List 中、创建 Map 和 Set,甚至丢弃每个返回值,只保留计算后的统计结果。你可以使用 ResultHandler 做很多事,这其实就是 MyBatis 构建 结果列表的内部实现办法。

从版本 3.4.6 开始,ResultHandler 会在存储过程的 REFCURSOR 输出参数中传递使用的 CALLABLE 语句。

它的接口很简单:

  1. package org.apache.ibatis.session;
  2. public interface ResultHandler<T> {
  3. void handleResult(ResultContext<? extends T> context);
  4. }

ResultContext 参数允许你访问结果对象和当前已被创建的对象数目,另外还提供了一个返回值为 Boolean 的 stop 方法,你可以使用此 stop 方法来停止 MyBatis 加载更多的结果。

使用 ResultHandler 的时候需要注意以下两个限制:

  • 使用带 ResultHandler 参数的方法时,收到的数据不会被缓存。
  • 当使用高级的结果映射集(resultMap)时,MyBatis 很可能需要数行结果来构造一个对象。如果你使用了 ResultHandler,你可能会接收到关联(association)或者集合(collection)中尚未被完整填充的对象。