一:
像 Hibernate 和 OJB 之类的对象映射工具都非常风行——并且应当如此。这些工具将 JDBC 从 JDBC 程序设计中分离出来,从而使得编写数据库访问代码如同处理文件 I/O 一样简单。
最近一个有影响力的对象映射工具是iBATIS-Database Layer。iBATIS 不同于其它对象映射工具的地方在于它不是将对象映射到数据库,而是将 SQL 映射为对象,反之将对象映射为 SQL。简单的映射基础使得具有 Java 和 SQL 经验的开发人员很容易开始使用 iBATIS。
iBATIS-Database Layer 的核心是 XML 文件,例如:
<mapped-statement name="loadEmployee" result-class="tips.Employee">
select
emp_id as id,
last_name as lastName,
first_name as firstName,
title as title,
from employees
where emp_id = #value#
</mapped-statement>
创建一个 Employee 对象的动作直接映射到一个 SQL 语句。
创建能够执行 SQL 的对象的方式如下:
public Employee getEmployeeById(Long id) {
Employee employee = (Employee) sqlMap.executeQueryForObject("loadEmployee",
id);
}
iBATIS-Database Layer 支持对各种手工数据库操作动作的映射:插入、更新及删除。它还具有其它对象映射工具的优点,比如说多数据库支持、数据源配置、将依赖对象映射为属性等等。使用 iBATIS 的另一个优点是其学习曲线比较温和,因为你已经了解了SQL,这就相当于了解了 iBATIS 的一半。然而,有其好处的同时也会有其(最起码是警告级的)坏处。
因为你是自己编写 SQL,所以你可能会在 SQL 中使用针对某个特定数据库的优化技术。使用针对特定数据库的 SQL 意味着如果你决定更换数据库那么你就必须移值你的映射。
即使有这种警告,iBATIS-Database Layer 依然值得考虑。自己衡量一下,看看这个框架对你是否有所帮助。
二:
EJB很重,不需要分布式的中小项目慎用,Hibernate虽好,公司缺少高水平的OO设计师,程序员水平参次不齐,iBatis是我本人比较喜好的半自动ORM东东。
持久层使用了iBatis后,团队中以前八仙过海的jdbc包装不见了,大家的编码风格统一了,会补长木桶较短的木板。大家不会再把精力浪费到分页 连接池 主键生成等地方了,可以集中精力进行业务组件的编写。
以下是个人感受:
1.缓存不用太可惜,不过具体用哪一种(MEMORY LUR FIFO OSCACHE)容量设多大,都得根据项目的实际情况来定,我通常首选LUR。正确设定缓存的Flush语句,杜绝缓存中脏数据产生的可能。缓存使用前提是,系统中对表的读写一定要都通过ibatis来进行,也就是封闭的。
2.动态SQL的确是个强点。熟悉后感觉很不错。iBatis中所有的DAO方法都只传一个值对象,复杂查询当然也不例外。
3.复杂对象一定要lazyload = true. 对于性能上有一定的好处。
4.iBatis其实已经把Dao接口和SQLMap实现层实现了解藕,感觉有点象Spring倡导的Ioc.
5.通常我会在写完Service接口后,直接写一个junit测试类,它是业务层和WEB层的连接点,进行测试很重要,一是方便重构后检测是否破坏了功能,另外,编写测试类也是一个掌握此类用法的过程。看着一排绿色的通过进度条,心情大好。
6.关于辅助工具:hibernate带的工具就很方便,iBatis的开发者好象觉得这个够简单了,没必要弄这么个工具。现在其官方网站的主页上有一个用Perl写的生成器,用表的DLL脚本作为源,自动化产生Pojo 和sqlMap xml配置文件,我down下来测试了一下,郁闷,60%都会报错,不知为何。我考虑用Java或delphi写一个简单易用的,有GUI的。如果有达人知道网上哪儿有了这么个东西,请告诉我,非常感谢。
三:关于iBatis的缓存使用
在你的xml配置文件中,每一个 cacheModel 元素,如下
<cacheModel id="oneday_cache" type="LRU" readOnly="false" serialize="true">
<flushInterval hours="24"/>
<flushOnExecute statement="updateMyDate"/>
<property name="size" value="200"/>
</cacheModel>
1 属性readOnly如果不写,默认是true,这时的缓存效果无疑最好,因为系统不需要考虑更新操作引起缓存与实际数据不一致的问题,只读缓存的例子是固化到数据库中的一些配置参数表。但是,通常我们想缓存的数据是需要增删改的,这时务必记得要加上 readOnly = "false";
2 属性serialize,如果不写,默认为false, 将它设为true,可以提高整体应用(而不仅仅是每个Session)的性能。 这种缓存为每一个Session返回缓存对象不同的实例(复本)。因此每一个Session都可以安全修改返回的对象. 注意,此时readOnly必须为false。
如果你把它设为 true ,记得检查两件事,一件事是缓存中存放的对象(你想查询的POJO)必须是可序列化的, 即实现Serializable接口。如果你有一个复杂对象属性,它也必须满足这个规则,你的整个对象树必须是可序列化的。
另一件事是关闭sql-map-config中的延迟加载属性,即lazyload=false,原因是,它使用了动态代理机制, 那个代理对象并不是Serializable的。
缓存类型的最佳适应情形:
MEMORY 没有统一的对象重用模式的应用,或内存不足的应用。
LRU 在较长的期间内,用户经常使用某些特定对象。
FIFO 用户在短时间内持续引用特定的查询,而后很可能不再使用。
根据个人实践,内存充足时使用LRU,否则使用MEMORY(WEAK)通常能获得较好的效果。