首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 软件管理 > 软件架构设计 >

mybatis学习课程-7Java API

2013-03-16 
mybatis学习教程-7Java APIselect * from Blog where id #{id}/select执行 N 次 session.selectOne(s

mybatis学习教程-7Java API
select * from Blog where id = #{id}
</select>
执行 N 次 session.selectOne("selectBlog", #{id}),就要创建N 个 PreparedStatement
对象,了解一下数据库引擎工作原理,就知道这样会带来不小的开销。
2. 使用ExecutorType.REUSE
session = factory.openSession(ExecutorType.REUSE);
对于 XML 映射配置文件中定义的所有 SQL 语句在执行时都由 Connection 创建一个
PreparedStatement 对象来执行。但 MyBatis 会把每条 SQL 语句的PreparedStatement 对象缓存
起来,等到下次再执行相同的 SQL 语句,则使用缓存的 PreparedStatement 对象。如,执行 N 次
session.selectOne("selectBlog", #{id}),只是创建一个 PreparedStatement 对象。
3. 使用ExecutorType.BATCH
执行批量更新,把要进行批量更新的 SQL 语句作为整体进行打包、编译、优化等,可减少网
络流量等。
MyBatis 3 - User Guide
58
语句执行方法组(Statement Execution Methods)
这些方法用来执行定义在 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 必须返回一个对象,如果返回一
个以上的对象或者返回0 个对象,将会抛出异常。如果不能预知会返回多少对象,最好使用
selectList 方法。如果您只是检测一下是否存在一个对象,可以使用 SQL 语法中的 COUNT 返回一
个计数(0 或者 1)。因为不是所有语句都需要传入参数的,因此这些方法可以重载为不需要参数
的版本。
Object selectOne(String statement)
List selectList(String statement)
int insert(String statement)
int update(String statement)
int delete(String statement)
最后,它们还有三个 select 方法的高级版本,允许您限定返回行记录的范围或者提供自定义
的结果处理逻辑。这三个方法一般用来处理大量的数据集
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
类有一个构造函数,设定偏移量或者指定条数,如果没进行设置,那就没有限制了。
int offset = 100;
int limit = 25;
RowBounds rowBounds = new RowBounds(offset, limit);
不同的驱动程序在这方面可以达到的效率是不同的。为了得到最好性能,使用
SCROLL_SENSITIVE 或者 SCROLL_INSENSITIVE 参数设置来返回结果集(换名话说,不要使用
FORWARD_ONLY)。
(译者注)默认情况下获得的结果集是不能更新的,且只有一个向前移动的光标。下面
MyBatis 3 - User Guide
59
ResultHandler 参数允许您按照自己喜欢的方式对每条记录进行操作。您能把每条记录加入
一个 list、Map 或者 Set,或者只是进行数量统计。您能让 ResultHandler 做许多事情,它同样
被 MyBatis 用来生成结果集列表(result set lists)。
这个接口非常简单:
package org.mybatis.executor.result;
public interface ResultHandler {
void handleResult(ResultContext context);
}
ResultContext 参数允许您访问结果对象本身,创建一定数量的结果对象,或者使用返回值
是 Boolean 的 stop()方法来停止加载更多的结果集。
事务控制方法组(Transaction Control Methods)
有四个控制事务作用域的方法,当然,如果您使用了自动提交或者正在使用的是外部事务管
理器,那这四个方法就没什么作用。然而,如果您使用由 Connection 实例管理的JDBC 的事务管
理器,那这四个方法就非常管用:
void commit()
void commit(boolean force)
void rollback()
void rollback(boolean force)
默认地MyBatis 不会自动提交,除非它检测到数据库被insert,update 或者 delete 改变。
如果在哪里作了修改而没有使用这些方法,那么,您需要传入 true 到 commit 和 rollback 方法,
以保证它会提交。注意:您依然不能把一个会话或者一个使用外部事务的管理器强制设成自动提
交模式。大部分时间,您不需要调用 rollback()方法,因为如果您不调用 commit 方法的话,
MyBatis 会为您进行回滚。然而,如果您需要在一个有多个提交或者多个回滚可能的会话中获得
更好(更细粒度)的控制,那么可以使用 rollback 选项来实现。
清除会话层缓存(Clearing the Session Level Cache)
是一个可更新可滚动的结果集:
Statement stmt = con.createStatement(
ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_UPDATABLE);
ResultSet rs = stmt.executeQuery("SELECT a, b FROM TABLE2");
MyBatis 3 - User Guide
60
void clearCache()
SqlSession 实例有一个本地缓存,这个缓存在每次提交,回滚和关闭时进行清除。如果不想
在每次提交或者回滚时都清空缓存,可以明确地调用clearCache()方法来关闭。
确保 SqlSession 已经关闭(Ensuring that SqlSession is Closed)
void close()
最重要的事情是要确保关闭已经打开的会话,而最好的方式来保证是用下面的模式:
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,您能够使用 SqlSession 的 getConfiguration()方法来获
得 Configuration 的实例。
Configuration getConfiguration()
使用 Mappers
<T> T getMapper(Class<T> type)
虽然前面提到的 insert, update, delete 和 select 方法很强大,但同时,它们也有点冗
长,且不是类型安全的,IDE 或者单元测试也帮助发现不了其中的错误。我们在文章最开始就看
到过使用 Mappers 的例子,我们可以回顾一下。
因此,一个最常用的方式是使用 Mapper 接口来执行映射语句。一个Mapper 接口定义的方法
要与 SqlSession 执行的方法相匹配,即Mapper 接口方法名与映射 SQL 文件中的映射语句 ID 相
同。下面例子演示了这种用法。
public interface AuthorMapper {
// (Author) selectOne(“selectAuthor”,5);
Author selectAuthor(int id);
// (List<Author>) selectList(“selectAuthors”)
List<Author> selectAuthors();
MyBatis 3 - User Guide
61
// insert(“insertAuthor”, author)
void insertAuthor(Author author);
// updateAuthor(“updateAuhor”, author)
void updateAuthor(Author author);
// delete(“deleteAuthor”,5)
void deleteAuthor(int id);
}
总体来说,每个Mapper接口方法签名,都要与一个SqlSession 的方法相对应,方法名也要与
映射语句的ID相对应。
另外,返回的类型要与期望的结果类型一致。支持返回所有类型,包括:基本数据类型,
Maps,POJOs 和 JavaBeans。
? Mapper 接口不需要实现任何接口或者继承任何类,只要方法签名能够唯一地与映射语句相对
应就可以了。
? Mapper 接口可以继承其它接口。当您使用 XML 绑定 Mapper 接口时,要确保在同一命名空间
里有您使用的语句。唯一的限制是不能同时有相同的方法签名在两个不同层次的接口。
您能够传递多个参数给mapper 方法,如果这么做,要它们默认的参数列表位置来命名,例如
这样:#{1}, #{2}等,如果您想改变参数的名字(多参数情况下),那您可以使用
@Param(“paramName”) 注解的方式来传入参数。
您同样也可以传递一个RowBounds 实例到方法,用来限定查询结果范围。
Mapper 注解
从很早的时候,MyBatis 就使用XML 驱动的框架,基于 XML 配置,映射语句都定义在
XML 中。在 MyBatis3 中,还有新的可选方案。MyBatis3 建立于广泛且强大的java 配置 API 之
上。java 配置 API 是基于XML 的 MyBatis 配置的基础,同时也是基于注解的配置基础。注解提供
了一个简单的方式来执行简单映射语句而不引入大量的开销。
? 注意:
很不幸,java 注解在表现力与灵活性上是有限的。尽管花了很多时间来研究,设计与
试验,但是强大的 MyBatis 映射不能够建立在注解之上。C#属性则不会有这种限制。虽然如此,
基于注解的配置并非没有好处的。
注解配置属性如下表:
注解
使用范围
等同XML
描述
@CacheNamespace
Class
<cache>
在指定的命令空间里配置缓存,如类
里。
属性有: implementation, eviction,
MyBatis 3 - User Guide
62
flushInterval, size 和 readWrite.
@CacheNamespaceRef
Class
<cacheRef>
引用另一个命名空间的缓存。
属性:value:命名空间名 (也就是完全
类路径名).
@ConstructorArgs
Method
<constructor>
收集一组结果集传入到一个结果对象的
构造器。
属性:value:参数对象的数组。
@Arg
Method
<arg>
<idArg>
单个构造器参数,是 ConstructorArgs
集合的一部分。
属性: Id, column, javaType,
jdbcType,typeHandler。
这个 id 属性值是一个字符串类型的值,
用于标识这个属性,并被用来进行比
较。类似于<idArg>这个XML 元素(原
文:The id attribute is a boolean
value that identifies the property
to be used for comparisons, similar
to the <idArg> XML element.说是
boolean 值应该有误)。
@TypeDiscriminator
Method
<discriminator>
一组 cases 值,用来决定哪一个结果会
被映射。
属性: column, javaType, jdbcType,
typeHandler, cases。
cases 属性是一个Cases 数组 。
@Case
Method
<case>
单个值的 case ,与映射对应。
属性:value, type,results。
Results 属性是一个结果集数组,因此
Case 注解与ResultMap 很相似,由下面
的 Results 注解指定。
@Results
Method
<resultMap>
结果映射集。其中包含如何将结果列映
射到属性或者字段的详细信息。
属性:
Value:一个结果集注解的数组。
@Result
Method
<result>
<id>
一个列和属性或字段之间的单个结果映
射。
属性:id, column, property,
javaType, jdbcType,typeHandler,
one, many。
这个 id 属性值是一个字符串类型的值,
用于标识这个属性,并被用来进行比
较。类似于<idArg>这个XML 元素。one
属性是单个association,与
<association>元素相似。它们的命名要
避免与类名相冲突。
MyBatis 3 - User Guide
63
@One
Method
<association>
映射到单个复杂类型属性。
属性:select:映射语句全称(也就是
映射方法),能够加载一个相应类型的
实例。
注意:您会发现连接映射没有被注解 API
支持。这就是注解的局限性,它不允许
循环引用。
@Many
Method
<collection>
映射到一个复杂类型的集合属性。
属性:select:映射语句全称(也就是
映射方法),能够加载一个相应集合的
实例。
注意:您会发现连接映射没有被注解 API
支持。这就是注解的局限性,它不允许
循环引用。
@Options
Method
映射语句属性
这个注解提供访问各种开关和配置选
项。Options 注解提供一致的和清晰的方
式来访问这些开关与配置。
属性:useCache=true,
flushCache=false,
resultSetType=FORWARD_ONLY,
statementType=PREPARED,
fetchSize=-1, timeout=-1,
useGeneratedKeys=false,
keyProperty=“id”。
理解 java 注解是很重要的,它没有指
定“null”作为一个值的方式。因此,
一旦使用 Options 注解,您的语句将使
用所有默认选项值。注意默认的值以避
免出现不是您所期待的行为结果。
@Insert
@Update
@Delete
@Select
Method
<insert>
<update>
<delete>
<select>
其中的每一个注解都代表着要被执行的
实际 SQL。它们都可以传入一个字符串数
组(或者单个字符串)。如果传递了一
个字符串数组,它们就会使用一个空格
将这些字符串分开,然后连接在一起。
这样帮助在java 代码中生成 SQL 语句时
避免空格丢失问题。当然如果您喜欢,
传入一条字符串也可以。
属性:value:传入的字符串数组。这些
数组将形成单一 SQL 语句。
@InsertProvider
@UpdateProvider
@DeleteProvider
@SelectProvider
Method
<insert>
<update>
<delete>
<select>
允许动态生成
SQL。
这些可选的SQL 注解允许您在运行的过
程中,执行指定类和方法返回的SQL 。
当执行映射语句时,MyBatis 将会实例
化 provider 指定的类,执行其中的方
法。这方法可选地接受参数对象作为它
唯一的参数,但必须只指定一个参数或
MyBatis 3 - User Guide
64
SelectBuilder
Java 开发人员最讨厌的事情就是不得不在java 代码中嵌入 SQL 语句。通常这样做的原因是
SQL 必须动态生成,要不然,您可以把 SQL 定义在外部文件或者存储过程中。正如您所看到的,
MyBatis 在它的XML 映射功能中对动态 SQL 的生成有一个很强大的解决方案。然而,有时候还是
不得不在 java 代码中生成SQL 语句字符串,这种情况下,MyBatis 还有一个功能可以帮助到您,
用于减少加号、引号、换行、格式问题和在嵌套条件中处理额外的逗号与AND 连词……事实上,
在 java 中动态生成SQL 代码可以说是一场真正的噩梦。
MyBatis3 引入一个稍微有点不同的概念来处理这个问题。我们可以生成一个类的实例,然后
调用这个实例的方法来一步生成一条 SQL 语句,最终的 SQL 看起来更像是 java 代码而不像 SQL 代
码。我们正在尝试不同的东西,最终结果接近一种领域特定语言(DSL),这也是java 目前形态
要达到的目标。

热点排行