iBATIS似乎已远离众说纷纭的OR框架之列, 通常人们对非常流行的Hibernate情有独钟。但正如Spring: A Developer's Notebook作者Bruce Tate 和Justin Gehtland所说的那样,与其他的OR框架相比,iBATIS独辟蹊径:“iBATIS不是试图从根本上掩盖SQL,实际上,它是在拥抱SQL。”
但 别犯愁:SQL本身具备了一些重要的功能,并且通过模板的使用,在Spring应用中采用iBATIS显得轻而易举。在此摘录中,两位作者将和你一起安装 iBATIS并将其集成进你的Spring应用中。他们也阐明了怎样取得你已编写的SQL语句及把他们映射给iBATIS使用的Bean。最后,还讨论了 iBATIS的优缺点,及为什么是这样的一种方式,即所谓的“在完全OR与JDBC之间的一个幽雅的折衷。”
就象Developer's Notebook 系列中所有的书一样,你将由直接的且实用的方式获得信息,这些信息包含了完成你工作所需的细节。换言之:“一切来自实战,没有讲义。”
对象关系持久化(OR Persistence)
本章所涉及的内容为:
· 与iBATIS的集成
· 在Spring的应用中使用JDO
· 在Spring的应用中使用Hibernate
· 运行测试用例
离 我住处不远的地方,名为啤酒山的山上有一个臭名远扬的山地自行车道。我想不出它为何会得到这样的名字,因为在下山的时候你要保持完全地清醒甚至于全神贯 注。据我所知,那决不是纯粹的攀爬(或不曾离开自行车步行)。大多数人认为那很荒谬,哪怕只是去尝试一下而已。这座山连绵起伏,异常陡峭,它的表面覆盖了 松散的岩石和大量的岩脊。我想我一定是太厌烦我的余生了,因为两年半来我一直不断地在攀爬。在我看来,那样的一座山峰就像是一个困难的编程问题。我已多次 重新启程,在到达山峰的途中,尝试过翻越许多岩脊和泥砾丛的不同途径。为了攀爬啤酒山, 我需要改良自行车,提高车技,加强训练。
对Java 开发人员而言,对象关系映射已然成为那类问题了。我们需要处理功能(processing power)、较佳设计模式及更好持久化框架的组合,从而使解决持久化设计变得更加清晰。最终,我们开始取得实质性的进展。现在,我们已逼近山峰,象 Spring这样的框架就象是方程式的一部分,因为他们让对象关系映射(ORM)花较少的精力来做更多的事情。在本章中,你将看到三种框架: iBATIS, JDO及Hibernate:
·iBATIS 是一种JDBC助手类框架,它给了你一些OR映射及使用OR的好处,但不带 有太多的风险。
·JDO是一种饱受争议的持久化标准,但它有着一些独特的实现,这使得JDO在行业中也算得上是最完美的持久化框架之一。
·Hibernate 是在JBoss组织控制下的一开源持久化框架。它可能是时下最为流行的持久化框架。大量的客户采用它,而且客户的数量还在持续稳定地增长。
在本章中,我们会对所提的三个框架进行尝试,而不必对应用的其余部分的代码做任何变更。
与iBATIS集成
常 言道:“树大招风”。在大肆宣扬的J2EE和.Net之争中, Sun的一示例应用程序被用来作为衡量应用服务器在运行时的各项性能的核心基准。 .Net非常好地打败了基于EJB的J2EE版本, 且方兴未艾。Clinton Begin 开发了iBATIS的持久化框架,他在iBATIS中使用PetStore的简化版,且自从那以后iBATIS就越来越流行。Spring提供非常优良的 与iBATIS的集成功能, 在此章中将对其进行介绍。
并非所有的问题都非常适合持久化框架这朵盛开的花朵,中等难度的问题是最合适的环 境。没有正确的技巧或不相称的问题,可能就会误入歧途。跟我一起教课的Ted Neward, 他是《Effective Enterprise Java》一书的作者,他经常把构建或采用持久化框架与美国的越南战争拿来做比较,进入这样的两场战争是很诱人的,但最终都很难赢得胜利,而且此二例中并 不存在着行之有效的策略。关于这一话题,你仍可查阅http://www.neward.net上的相关内容。
public class IBatisRentABike extends SqlMapDaoSupport
implements RentABike {
private String storeName ="";
public void setStoreName(String storeName) {
this.storeName= storeName;
}
public String getStoreName( ) {
return this.storeName;
}
public List getBikes() {
return getSqlMapTemplate().executeQueryForList("getBikes", null);
}
public Bike getBike(String serialNo) {
return (Bike) getSqlMapTemplate().
executeQueryForObject("getBikeBySerialNo", serialNo);
}
public Bike getBike(int bikeId) {
return (Bike) getSqlMapTemplate().
executeQueryForObject("getBikeByID", new Integer(bikeId));
}
public void saveBike(Bike bike) {
getSqlMapTemplate().executeUpdate("saveBike", bike);
}
public void deleteBike(Bike bike) {
getSqlMapTemplate().executeUpdate("deleteBike", bike);
}
public List getCustomers() {
return getSqlMapTemplate().executeQueryForList("getCustomers", null);
}
public Customer getCustomer(int custId) {
return (Customer) getSqlMapTemplate().
executeQueryForObject("getCustomer", new Integer(custId));
}
public List getReservations() {
return getSqlMaptemplate().
executeQueryForList("getReservations", null);
}
public List getReservations(Customer customer) {
return getSqlMaptemplate().
executeQueryForList("getReservationsForCustomer", customer);
}
public List getReservations(Bike bike) {
return getSqlMaptemplate().
executeQueryForList("getReservationsForBike",bike);
}
public List getReservations(Date date) {
return getSqlMaptemplate().
executeQueryForList("getReservationsForDate", date);
}
public Reservation getReservation(int resId) {
return getSqlMaptemplate().
executeQueryForObject("getReservation", new Integer(resId));
}
}
<?xml version="1.0" encoding="UTF-8" ?>
<sql-map name="Bike" >
<result-map name="result" class="com.springbook.Bike" >
<property name="bikeId" column="bikeId" columnIndex="1" />
<property name="manufacturer" column="manufacturer" columnIndex="2" />
<property name="model" column="model" columnIndex="3" />
<property name="frame" column="frame" columnIndex="4" />
<property name="serialNo" column="serialNo" columnIndex="5" />
<property name="weight" column="weight" columnIndex="6" />
<property name="status" column="status" columnIndex="7" />
</result-map>
<mapped-statement name="getBikes" result-map="result">
select bikeId, manufacturer, model, frame, serialNo, status
from bikes
</mapped-statement>
<mapped-statement name="getBikeBySerialNo" result-map="result">
select bikeId, manufacturer, model, frame, serialNo, status
from bikes
where serialNo=#value#
</mapped-statement>
<mapped-statement name="getBikeByID" result-map="result">
select bikeId, manufacturer, model, frame, serialNo, weight, status
from bikes
where bikeId=#value#
</mapped-statement>
<mapped-statement name="saveBike" >
insert into bikes
(bikeId, manufacturer, model, frame, serialNo, weight, status)
values(#bikeId#, #manufacturer#, #model#, #frame#, #serialNo#,
#weight#, #status#)
</mapped-statement>
<mapped-statement name="deleteBike" >
delete from bikes
where bikeId = #bikeId#
</mapped-statement>
</sql-map>