批量执行更新方法
- 有一个方法可以刷新(执行)存储在JDBC 驱动类中的批量更新语句。当你将 ExecutorType.BATCH 作为 ExecutorType 使用时可以采用此方法。
List<BatchResult> flushStatements()
事务控制方法
- 控制事务作用域有四个方法。当然,如果你已经设置了自动提交或你正在使用外部事务管理器,这就没有任何效果了。然而,如果你正在使用 JDBC 事务管理器,由Connection 实例来控制,那么这四个方法就会派上用场:
void commit() void commit(boolean force) void rollback() void rollback(boolean force)
- 默认情况下 MyBatis 不会自动提交事务,除非它侦察到有插入、更新或删除操作改变了数据库。如果你已经作出了一些改变而没有使用这些方法,那么你可以传递 true 到commit 和 rollback 方法来保证事务被正常处理(注意,在自动提交模式或使用了外部事务管理器的情况下 force 值对 sesssion 无效)。很多时候你不用调用 rollback() , 因为 MyBatis 会在你没有调用commit 时替你完成回滚操作,然而 如果你要在支持多提交和回滚session 中获得更多细粒度的控制. 你可以使用回滚操作来达到目的。
- MyBatis-Spring 和 MyBatis-Gurice 提供了声明式事务处理,如果你在使用MyBatis 的同时使用了 Spring 或 Gurice . 请参考他们的官方手册获取更多的信息。
本地缓存
- Mybatis 使用到了两种缓存:本地缓存(local cache)和二级缓存(second level cache)。
- 每当一个新 session 被创建,MyBatis 就会创建一个与之相关联的本地缓存。任何在 session 执行过的查询语句本身都会被保存在本地缓存中,那么,相同的查询语句和相同的参数所产生的更改就不会二度影响数据库了。本地缓存会被增删改、提交事务、关闭事务以及关闭 session 所清空。
- 默认情况下,本地缓存数据可在整个 session 的周期内使用,这一缓存需要被用来解决循环引用错误和加快重复嵌套查询的速度,所以它可以不被禁用掉,但是你可以设置 localCacheScope=STATEMENT 表示缓存仅在语句执行时有效。
- 注意,如果 localCacheScope 被设置为 SESSION, 那么 MyBatis 所返回的引用将传递给保存在本地缓存里相同的对象。返回的对象(例如:list)做出任何更新将会影响本地缓存的内容,而影响存活在 session 生命周期中的缓存缩所返回的值。因此,不要对MyBatis 所返回的对象做任何更改以防后患。
- 清空本地缓存
void clearCache()
关闭SqlSession
void close()
- 你必须保证的最重要的事情是你要关闭所打开的任何 session。保证做到这点的最佳方式是下面的工作模式:
try (SqlSession session = sqlSessionFactory.openSession()) { // following 3 lines pseudocod for "doing some work" session.insert(...); session.update(...); session.delete(...); session.commit(); }
- 就像 SqlSessionFactory , 你可以通过调用当前使用的 SqlSession 的 getConfiguration 方法来获得 Configuration 实例。
Configuration getConfiguration()
使用映射器
<T> T getMapper(Class<T> type)
- 上述的各个 insert、update、delete 和 select 方法都很强大,但是也很繁琐,可能会长兴类型安全问题并且对于你的 IDE和单元测试也没有实质性的帮助。在上面的人们章节中我们看到了一个使用映射器的实例。
- 因此,一个更通用的方式来执行映射语句是使用映射器类。 一个映射器类就是一个仅需什么与SqlSession 方法匹配的方法的接口类。下面的示例展示了一些方法签名以及他们是如何映射到 SqlSession 上。
public interface BlogMapper { Blog get(String id); List<Blog> select(); void insert(Blog dto); void update(Blog dto); }
- 总之,每个映射器方法签名应该匹配相关的 SqlSession 方法,而字符串参数ID则无需匹配,相反,方法名必须配映射语句的ID
- 此外,返回类型必须匹配期望的返回类型, 单返回值时为所指定类的值,多返回值是为数据或集合。所有常用的类型都是支持的,包括:原生类型、Map、POJO 和 JavaBean.
- 映射器接口不需要去实现任何接口或继承任何类,只要方法可以被唯一标识对应的映射语句就可以了
- 映射器接口可以继承其他接口,当使用 XML来构建映射器接口时要保证语句被包含在合适的命名空间中。而且唯一的限制就是你不能在两个继承关系的口中拥有相同的方法签名(潜在的危险做法不可取)
- 你可以传递多个参数给一个映射器方法。如果你这样做了,默认情况下它们将会以 "param" 字符串紧跟着它们在参数列表中的位置来命名,比如:#{param1}、#{param2}等。如果你想改变参数的名称(只在多参数情况下),那么你可以在参数上使用 @Param("paramName") 注解。
映射器注解
- 因为最初设计时,MyBatis 是一个 XML 驱动的框架。配置信息是基于 XML 的,而且映射语句也是定义在 XML 中的。而到了 MyBatis 3,就有新选择了。MyBatis 3 构建在全面且强大的基于 Java 语言的配置 API 之上。这个配置 API 是基于 XML 的 MyBatis 配置的基础,也是新的基于注解配置的基础。注解提供了一种简单的方式来实现简单映射语句,而不会引入大量的开销。
- 注意 不幸的是,Java 注解的的表达力和灵活性十分有限。尽管很多时间都花在调查、设计和试验上,最强大的 MyBatis 映射并不能用注解来构建——并不是在开玩笑,的确是这样。比方说,C#属性就没有这些限制,因此 MyBatis.NET 将会比 XML 有更丰富的选择。也就是说,基于 Java 注解的配置离不开它的特性。
映射器示例
- 通过 @SelectKey 注解来读取自增列的唯一主键ID
//mapper @InsertProvider(type = BlogProvider.class, method = "insertSql") @SelectKey(statement = "select last_insert_id()", keyProperty = "id", keyColumn = "id", before = false, resultType = long.class) void insert(Blog dto); //provider public String insertSql() { return new SQL() .INSERT_INTO("blog") .INTO_COLUMNS("id", "name", "title", "content") .INTO_VALUES("#{id}", "#{name}", "#{title}", "#{content}") .toString(); }
- 或者通过 @Options 注解来读取自增列的唯一主键ID
//mapper @InsertProvider(type = BlogProvider.class, method = "insertSql") @Options(useGeneratedKeys = true, keyProperty = "id") void insert(Blog dto);
- 通过 @Result 的id 来获取结果集
@SelectProvider(type = BlogProvider.class, method = "findAllSql") @Results(id = "resultMap", value = { @Result(id = true, column = "id", property = "id"), @Result(column = "author_id", property = "authorId"), @Result(column = "name", property = "name"), @Result(column = "title", property = "title"), @Result(column = "content", property = "content"), }) List<Blog> finAll(); @SelectProvider(type = BlogProvider.class, method = "findBlogLikeSql") @ResultMap(value = {"resultMap"}) List<Blog> findBlogLike(@Param("name") String name, @Param("title") String title, @Param("content") String content);
- 多个参数使用 @SqlProvider 注解
//mapper @SelectProvider(type = BlogProvider.class, method = "findBlogLikeSql") @ResultMap(value = {"resultMap"}) List<Blog> findBlogLike(@Param("name") String name, @Param("title") String title, @Param("content") String content); //provider public String findBlogLikeSql(@Param("name") String name, @Param("title") String title, @Param("content") String content) { return new SQL() {{ SELECT("name, title, content"); FROM("blog"); if (name != null) { WHERE("name like #{name}"); } if (title != null) { WHERE("title like #{title}"); } if (content != null) { WHERE("content like #{content}"); } }}.toString(); }