MyBatis 教程

MyBatis SqlSession 类

在 MyBatis 中 SqlSession 类是非常强大的一个类。在这里你会发现所有 SQL 语句执行方法、事务提交、事务回滚均来自 SqlSession 类。

注意:每个线程都应该有它自己的 SqlSession 实例。SqlSession 的实例不能被共享,且是线程不安全的,因此最佳的范围是请求或方法范围。

绝对不能将 SqlSession 实例的引用放在一个类的静态字段甚至是实例字段中。也绝不能将 SqlSession 实例的引用放在任何类型的管理范围中,比如 Serlvet 架构中的 HttpSession。

如果你现在正用任意的 Web 框架,要考虑 SqlSession 放在一个和 HTTP 请求对象相似的范围内。

换句话说,基于收到的 HTTP 请求,你可以打开了一个 SqlSession,然后返回响应,就可以关闭它了。

关闭 Session 很重要,你应该确保使用 finally 块来关闭它。下面的示例就是一个确保 SqlSession 关闭的基本模式:

SqlSession session = sqlSessionFactory.openSession();
try {
    // do work
} finally {
    session.close();
}

在你的代码中一贯地使用这种模式,将会保证所有数据库资源都正确地关闭(假设你没有通过你自己的连接关闭,这会给 MyBatis 造成一种迹象表明你要自己管理连接资源)。

SQL 语句执行方法

这些方法被用来执行定义在 SQL 映射的 XML 文件中的 SELECT,INSERT,UPDATE 和 DELETE 语句。它们都会自行解释,每一句都使用语句的 ID 属性和参数对象,参数可以是原生类型(自动装箱或包装类),JavaBean,POJO 或 Map。

// 查询数据,只能返回一条记录,多于一条抛出错误
Object selectOne(String statement, Object parameter)
// 查询数据,返回一个列表
List selectList(String statement, Object parameter)
// 插入数据到数据库
int insert(String statement, Object parameter)
// 更新数据库数据
int update(String statement, Object parameter)
// 删除数据库数据
int delete(String statement, Object parameter)

selectOne 和 selectList 的不同仅仅是 selectOne 必须返回一个对象。如果多余一个,或者没有返回(或返回了 null),那么就会抛出异常。如果你不知道需要多少对象,使用 selectList。

如果你想检查一个对象是否存在,那么最好返回统计数(0 或 1)。因为并不是所有语句都需要参数,上面这些方法都有不同版本的重载,它们可以不需要参数对象。如下:

// 无任何参数,获取单条数据
Object selectOne(String statement)
// 无任何参数,获取数据列表
List selectList(String statement)
// 无任何参数,插入数据
int insert(String statement)
// 无任何参数,更新数据
int update(String statement)
// 无任何参数,删除数据
int delete(String statement)

最后,还有三个高级版本的查询方法,它们允许你限制返回行数的范围,或者提供自定义结果控制逻辑,这通常用于大量的数据集合。

// 分页查询
List selectList(String statement, Object parameter, RowBounds rowBounds)
// 自定义结果处理器
void select(String statement, Object parameter, ResultHandler handler)
// 分页和自定义结果处理器
void select(String statement, Object parameter, RowBounds rowBounds, ResultHandler handler)

RowBounds 参数会告诉 MyBatis 略过指定数量的记录,还有限制返回结果的数量。RowBounds 类用一个构造方法来接收 offset 和 limit,否则是不可改变的。

int offset = 100;
int limit = 25;
RowBounds rowBounds = new RowBounds(offset, limit);

ResultHandler 参数允许你按你喜欢的方式处理每一行。你可以将它添加到 List 中,创建Map,Set 或抛出每个结果而不是只保留总计。你可以使用 ResultHandler 做很多漂亮的事,那就是 MyBatis  内部创建结果集列表。它的接口很简单。

package org.mybatis.executor.result;

public interface ResultHandler {
    void handleResult(ResultContext context);
}

ResultContext 参数提供了访问结果对象自身的方法,大量结果对象被创建,你可以使用返回布尔值的 stop() 方法来停止 MyBatis 加载更多的结果。

事务控制方法

控制事务范围有四个方法。当然,如果你已经选择了自动提交或你正在使用外部事务管理器,这就没有任何效果了。然而,如果你正在使用 JDBC 事务管理器,由 Connection 实例来控制,那么这四个方法就会派上用场:

// 提交事务
void commit()
void commit(boolean force)
// 回滚事务
void rollback()
void rollback(boolean force)

默认情况下 MyBatis 不会自动提交事务,除非它侦测到有插入,更新或删除操作改变了数据库。如果你已经改变了数据库数据,而没有使用插入、更新或删除方法,那么你可以传递 true 到 commit 和 rollback 方法来保证它会被提交。很多时候你不用调用 rollback(),因为如果你没有调用 commit 时 MyBatis 会替你完成。然而,如果你需要对 session 更细粒度的事务提交和回滚控制,你可以选择使用回滚来使它成为可能。

清理 Session 级的缓存

void clearCache()

SqlSession 实例有一个本地缓存,在执行 update,commit,rollback 和 close 时被清理。要明确地关闭它,你可以调用 clearCache() 方法。

确保 SqlSession 被关闭

void close()

你必须保证关闭所打开的任何 session。保证做到这点的最佳方式是下面的工作模式:

SqlSession session = sqlSessionFactory.openSession();
try {
    // following 3 lines pseudocod for “doing some work”
    session.insert(…);
    session.update(…);
    session.delete(…);
    session.commit();
} finally {
    session.close();
}

注意:就像 SqlSessionFactory,你可以通过调用 getConfiguration() 方法获得 SqlSession 使用的 Configuration 实例。

使用映射器

<T> T getMapper(Class<T> type)

上述的各个 insert,update,delete 和 select 方法都很强大,但也有些繁琐,没有类型安全,对于你的 IDE 也没有帮助。在上面的“MyBatis 入门实例”中我们已经看到了一个使用映射器的示例。

因此,一个更通用的方式来执行映射语句是使用映射器类。一个映射器类就是一个简单的接口,其中的方法定义匹配于 SqlSession 方法。下面的示例展示了一些方法签名和它们是如何映射到 SqlSession 的。

public interface AuthorMapper {
    // (Author) selectOne(“selectAuthor”,5);
    Author selectAuthor(int id);
    // (List<Author>) selectList(“selectAuthors”)
    List<Author> selectAuthors();
    // insert(“insertAuthor”, author)
    void insertAuthor(Author author);
    // updateAuthor(“updateAuhor”, author)
    void updateAuthor(Author author);
    // delete(“deleteAuthor”,5)
    void deleteAuthor(int id);
}

总之,每个映射器方法签名应该匹配相关联的 SqlSession 方法,而没有字符串参数 ID。相反,方法名必须匹配映射语句的 ID。

此外,返回类型必须匹配期望的结果类型。所有常用的类型都是支持的,包括:原生类型,Map,POJO 和 JavaBean。

映射器接口不需要去实现任何接口或扩展任何类。只要方法前面可以被用来唯一标识对应的映射语句就可以了。

映射器接口可以扩展其他接口。当使用 XML 来构建映射器接口时要保证在合适的命名空间中有语句。而且,唯一的限制就是你不能在两个继承关系的接口中有相同的方法签名(这也是不好的想法)。

你可以传递多个参数给一个映射器方法。如果你这样做了,默认情况下它们将会以它们在参数列表中的位置来命名,比如:#{1}, #{2} 等。如果你想改变参数的名称(只在多参数情况下),那么你可以在参数上使用 @Param("paramName") 注解。

说说我的看法
全部评论(
没有评论
关于
本网站属于个人的非赢利性网站,转载的文章遵循原作者的版权声明,如果原文没有版权声明,请来信告知:hxstrive@outlook.com
公众号