这一章包括:
				
		
		
				
				
						n     
				
				
				
						使用
				
				
						DAO
				
				
						模式创建抽象层。
				
		
		
				
				
						n     
				
				
				
						使用层的父型模式简化
				
				
						resource cleanup
				
				
						(资源清除)代码
				
		
		
				
				
						n     
				
				
				
						用
				
				
						spring
				
				
						组织你的项目
				
		
		
				
						 
				
		
		
				理解
				Hibernate
				的底层将需要很长一段时间才能在你的项目上使用。但是在
				Hibernate
				库的基础之外,如
				SessionFactory
				(会话工厂), 
				Session
				(会话), 
				mapping files
				(
				映射文件)和
				hibernate Query Language(HQL)
				(
				Hibernate
				查询语言),在一定高度组织一个应用程序并不是总是那么清楚的。 你能在你的项目中应用一些模式和好的经验。一些好的经验来自于社区;而另外一些来自应用于持久化的Java企业模式。这一章的目的就是带给你这些。
		
		
				
						    
				
				写程序有点像用小朋友的
				alphabet blocks
				(译者注:一种表面有字母的积木)建塔。如果你是建个小塔,那么你不需要仔细关心是怎么堆的。但如果你建一个大的塔,那么你可能要站得更高,你需要稍微不同的技术设置。多一点计划,多一点怎样堆的技术和可能使用一些超强的粘合剂。
		
		
				
						    
				
				无论是建立玩具塔还是写软件都要使用好的工具和技术。因此这一章就是怎样建立一座高塔。我们将讨论一些普通的模式:
				Data Access Object(DAO)
				(
				封装底层数据操作
				)和层的父型模式。另外,
				spring
				 ,
				流行的开源项目将为简化你的代码提供组织的工具。总之,这一章将给这个工具一个总的看法和怎样简化你的
				Hibernate
				项目。
		
		
				
						 
				
		
		
				
						章节目标:
				
		
		
				在这一章,你将完成一些几点:
		
		
				
				
						n        
				
				
				创建抽象层,使用
				DAO
				模式集中
				SQL
				语句,因此简化客户端对象使用。
		
		
				
				
						n        
				
				
				使用层的父型模式改善
				DAO
				对象,简化
				resource
cleanup
				(资源清除)代码。
		
		
				
				
						n        
				
				
				使用
				spring
				组织和简化你的
				DAO
				代码。
		
		
				
						 
				
		
		
				
						前提条件:
				
		
		
				假设你已经完成以下几点:
		
		
				
				
						n        
				
				
				熟悉模式的概念。
		
		
				
				
						n        
				
				
				理解
				session
				(会话)和
				transaction
				(事务)的工作原理,特别是怎样使用持久化被打开
				session
				(会话)链接的对象。
		
		
				
				
						n        
				
				
				你正在寻找一种能组织大型项目的技术。也就是说,使用好的框架代码将利于项目的以后的扩展。
		
		
				
						 
				
		
		
				
						7.1 
				
				
						无处不在的
				
				
						DAO
				
				
						模式
				
		
		
				大多数
				Java/J2EE
				开发者都或多或少熟悉
				DAO
				模式。它是
				Sun
				公司特地在
				Java
				蓝图中强调的核心模式之一,在许多
				Java
				书籍中都提到过。它是在使用持久化数据存储的应用程序中的采取的第一个首要模式。一般使用在使用
				SQL
				的应用程序中,同样也适用于
				Hibernate
				的应用程序。
		
		
				
						 
				
		
		
				
						
								7.1.1
						
				
				
						
						
				
				
						集中
				
				
						HQL
				
				
						
								
								
						
				
		
		
				DAO
				模式的目的能在在一个简单问题的答案中找到:你的数据操作代码放在哪里?如果你面对一个遗留程序而苦恼,因为这个程序中
				SQL
				代码就像鸟枪发射那样四处都是,而你又没有这方面的经验。其实这并没什么。需要从新命名表中的列吗?准备好手中的枪,在整个程序中修改,以确保你没有遗漏任何
				SQL
				语句。
		
		
				DAO
				模式鼓励开发者集中
				SQL
				语句。那么怎样才是好的
				SQL
				和
				HQL
				呢?在应用程序中将
				HQL
				放在一个地方以便以后更容易维护和修改。新手可能不能很好的确定将
				HQL
				放在哪?他们将
				HQL
				放在DAO中。
				Figure 7.1
				显示了
				Event
				和
				EventDao
				怎样和数据库互动。
		
		
				
						
						
						 
						
						
						
				
		
		
				
						Figure 7.1 
				
				Event
				和
				EventDao
				与数据库互动的图
		
		
				
						 
				
		
		
				通过前面章节知道,一个健壮的对象查询语句需要有错误处理管理,事务和
				resource cleanup
				(资源清除)。在余下的程序中最好隐藏以上那些。例如接下来的
				Hibernate
				程序,使程序更容易改变
				ORM
				(
				object/relational mapping
				)
				(
				对象关系映射
				)实现(例如:改变成
				JDO
				)1。更重要的是,这个策略简化了客户端怎样和持久化层互动;他们不需要知道
				session
				(会话), 
				transaction
				(事务)的边界,或者在他们使用之后是否被清除。
		
		
				
						 
				
		
		
				
						DAO
				
				
						也有类型
				
		
		
				
						    
				
				你能使用
				DAO
				两种基本类型中的一种:
		
		
				
				
						n        
				
				
				应用级
				DAO(DAO per application)
				:在一个应用中有一个中心的
				DAO
				对所有的实体对象添、删、改、查。
		
		
				
				
						n        
				
				
				类级
				DAO(DAO per class)
				:每个实体类都有自己的
				DAO
				,用于自身实例的添、删、改、查。
				Event
				对象由
				EventDao
				负责。
		
		
				你也可以应用其他镜像变量,例如使用模块级
				DAO(DAO per module)
				,但是最终的选择还是依赖于你有少个持久化对象。在有许多类的情况下,我们偏爱使用类级DAO策略。应用级
				DAO
				策略会出现“
				bloatware
				”类。第二,与类级
				DAO
				命名对称能更好的记忆。如果你需要找到
				Event
				类,你就能够记得起它的
				DAO
				是
				EventDao
				。最后,它满足开-关原则,原则规定类将因为扩充而打开,因为修改而关闭。你能够添加一个新的持久化类,而不需要修改中心的
				DAO
				。因此,让我们在示例中使用类级
				DAO
				。
		
		
				
						 
				
		
		
				
						简单的
				
				
						DAO
				
				
						
								
								
						
				
		
		
				
						    
				
				Listing 7.1
				
				
				显示了一个简单的
				DAO
				,它能处理满足大多数实体需要的基本的CRUD(添、删、改、查)业务。除了这些功能,它还有一些功能,因此客户端对象不用担心。
		
		
				
				
						n        
				
				
				包括业务级
				session
				(
				session per operation
				)
				;每个
				session
				(会话)都有添、删、改、查方法。
		
		
				
				
						n        
				
				
				提供一个业务级
				transaction
				(事务)
				(transaction
per operation)
				。客户端对象不用担心开始和提交事务。
				
						
						
				
		
		
				
				
						n        
				
				
				在
				Hibernate2.1
				中,处理捕获和
				Hibernate
				抛出的预期异常,将它们变为非预期异常,将不会使客户端代码混乱。如果你使用
				Hibernate3.x
				,你能够让没有从新抛出的非预期异常通过。(
				In Hibernate 2.x, handles catching and handling
the checked exceptions that Hibernate throws, turning them into unchecked
exceptions, which won’t clutter up client code. If you use Hibernate 3.x, you
can just let the unchecked 
				HibernateException
				s go without rethrowing
				.
				)
				
						
						
				
		
		
				
				
						n        
				
				
				输入特性鲜明和明确的
				DAO
				;
				EventDat
				仅为
				Event
				工作,意思就是客户端代码不必执行手动的操作。(
				Features strongly typed and
explicit DAOs; the 
				EventDao 
				only
works with 
				Event
				s, meaning client code
doesn’t have to perform manual casting.
				)
				
						
						
				
		
		
				
						 
				
		
		
				
						Listing 7.1 
				
				
						一个简单的有
				
				
						添、删、改、查方法的
				
				
						EventDao
				
				
						
								
								
						
				
		
		
				---------------------------------------------------------------------------------------------
		
		
				
				package
				 com.manning.hq.ch07;
 
				import
				 org.hibernate.HibernateException;
				import
				 org.hibernate.Session;
				import
				 org.hibernate.Transaction;
				import
				 org.apache.commons.logging.Log;
				import
				 org.apache.commons.logging.LogFactory;
				import
				 com.manning.hq.ch07.Event;
				import
				 com.manning.hq.ch07.HibernateFactory;
				import
				 java.util.List;
				/**
				
						
* DAO管理持久Evnet
				*/
				
						
				
				public
				 
				class
				 SimpleEventDao {
    Log log 
				=
				 LogFactory.getLog(SimpleEventDao.
				class
				);
				    private
				 Session session;
				    private
				 Transaction tx;
				    public
				 SimpleEventDao() {
        HibernateFactory.buildIfNeeded();
				//
				初始化SessionFactory。
				
				
				
						
    }
 
				    public
				 
				void
				 create(Event event) 
				throws
				 DataAccessLayerException {
				        try
				 {
            startOperation();
				//
				打开Session和开始transaction
				
				
				
						
            session.save(event);
				//
				保存Event。
				
				
				
						
            tx.commit();
        } 
				catch
				 (HibernateException e) {
            handleException(e);Rolls back和抛出异常。
        } 
				finally
				 {
            HibernateFactory.close(session);
        }
    }
				    public
				 
				void
				 delete(Event event) 
				throws
				 DataAccessLayerException {
				        try
				 {
            startOperation();
            session.delete(event);
            tx.commit();
        } 
				catch
				 (HibernateException e) {
            handleException(e);
        } 
				finally
				 {
            HibernateFactory.close(session);
        }
    }
				    public
				 Event find(Long id) 
				throws
				 DataAccessLayerException{
        Event event 
				=
				 
				null
				;
				        try
				 {
            startOperation();
            event 
				=
				 (Event) session.load(Event.
				class
				, id);
            tx.commit();
        } 
				catch
				 (HibernateException e) {
            handleException(e);
        } 
				finally
				 {
            HibernateFactory.close(session);
        }
				        return
				 event;
    }
				    public
				 
				void
				 update(Event event) 
				throws
				 DataAccessLayerException {
				        try
				 {
            startOperation();
            session.update(event);
            tx.commit();
        } 
				catch
				 (HibernateException e) {
            handleException(e);
        } 
				finally
				 {
            HibernateFactory.close(session);
        }
    }
				    private
				 
				void
				 handleException(HibernateException e) 
				throws
				 DataAccessLayerException {
        HibernateFactory.rollback(tx);
				        throw
				 
				new
				 DataAccessLayerException(e);
				        //
				 二选一,你能够从新抛出,就像…
				        //
				 throw e;
				
				
				
						
    }
				    private
				 
				void
				 startOperation() 
				throws
				 HibernateException {
        session 
				=
				 HibernateFactory.openSession();
        tx 
				=
				 session.beginTransaction();
     }
}
				package
				 com.manning.hq.ch07;
				public
				 
				class
				 DataAccessLayerException 
				extends
				 RuntimeException {
				//
				其他的构造函数省略。
				
				
				
						
				
				    public
				 DataAccessLayerException(Throwable cause) {
				        super
				(cause);
    }
}
		
		
		
				
						
								
								
						
				
		
		
				---------------------------------------------------------------------------------------------
		
		
				
						    
				
				SimpleEventDao
				是个极其简单的
				DAO
				,它有添,删,改,查四种方法。每种方法在一个 
				transaction
				(事务),打开和关闭一个
				session
				(会话)范围内处理业务。它是明确的,也就是说每个
				Event
				都有独有的业务处理,因此客户端类不需要再处理这些了。当这个实现是简单的(以后可能随着扩展会变大),客户端代码在运行
				event
				时代码就会变得很短。(
				While this implementation is simple (perhaps overly so, as we will explore
here later), it greatly shortens the client code that works with events.
				)因此创建和查询一个event就象下面的一样简单:---------------------------------------------------------------------------------------------
		
		
				
				Event event 
				=
				 
				new
				 Event();
event.setName(
				"
				A new Event
				"
				);
EventDao eventDao 
				=
				 
				new
				 EventDao();
eventDao.create(event);
Event foundEvent 
				=
				 eventDao.find(event.getId());
		
		
				
						
						
				
		
		
		
		
				------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
		
		
				正如你看到的,不需要处理凌乱的异常,这里也不需要处理
				resource cleanup
				(资源清除)。现在让我们讨论更多一些这个实现出现的问题,并且我们该怎样提高它。
		
		
				
						 
				
		
		
				
						7.2 
				
				
						分析
				
				
						DAO
				
				
						
								
								
						
				
		
		
				
						    
				
				我们在前面章节练习的简单的DAO实现出现了一些问题,有些你或许已经遇到。让我们看一看。
		
		
				
						 
				
		
		
				
						
								7.2.1
						
				
				
						
						
				
				
						boilerplate
code
				
				
						(
				
				
						样板代码)
				
				
						
								
								
						
				
		
		
				Listing 7.1 
				包括许多资源管理和异常处理代码。每个方法都有打开
				session
				(会话),开始事务,执行自己的商务业务,提交事务,事务回滚,最后关闭
				session
				(会话)。每个方法基本就像下面那样:
		
		
				-------------------------------------------------------------------------------
		
		
				
				
				
				
				
				  
				try
				 {
				
				
				
				
				
						
				     startOperation();
     session.save(event);
     tx.commit();
 } catch (HibernateException e) {
     handleException(e);
 } finally {
     HibernateFactory.close(session);
 }
		
				
						
						
				
		
		
		
		
				-------------------------------------------------------------------------------
		
		
				Session.save(event)
				这一行是每个方法中唯一改变的。甚至
				refactoring
				几个便利的方法(译者注:找了不少词典,都没有找到“
				refactor
				”),如
				startOperation
				()
				和
				handleException
				()
				,都不能完全摆脱你的样板代码。(
				Even
refactoring out a few convenience methods,such as 
				startOperation() 
				and 
				handleException()
				, doesn’t completely rid you
of boilerplate code
				)一个
				potential solution
				(潜在的解决方案)就是在7.3节讨论的层的父型模式。
		
		
				
						 
				
		
		
				
						
								
										7.2.2
								
						
						
								
								
						
						
								P
						
				
				
						otential
duplication
				
				
						(
				
				
						潜在的复制)
				
		
		
				
						    
				
				增加一个新的
				DAO
				变得很简单,只需要复制和粘贴。如果你需要其他的
				DAO
				,如
				LocationDao
				,
				我们将复制和粘贴
				EventDao
				,然后在每个方法中改变关联的少许几行代码。因为我们知道复制是所有程序的恶魔之首,显然需要做点事情。建立层的父型模式是非常有帮助的。
		
		
				
						 
				
		
		
				
						
								7.2.3
						
				
				
						游离对象
				
		
		
				
						    
				
				因为每个方法都是与单一的
				session
				(会话)和
				transaction
				(事务)运作的,与
				DAO
				运作的所有的
				Event
				是严格的游离对象。这个行为也许是美好的,但它不能够利用
				Hibernate
				的自动脏对象检查和
				session-level
object cache
				(会话级对象缓存)。例如,假如客户端这样写:
		
		
				---------------------------------------------------------------------------------------------
		
		
				
				Event foundEvent 
				=
				 eventDao.find(event.getId());
foundEvent.setDuration(
				30
				);
eventDao.update(foundEvent);
		
		
				
						
								
								
						
				
		
		
				---------------------------------------------------------------------------------------------
		
		
				Find
				运行在一个
				session
				(会话)中,
				update
				运行在另一个
				session
				(会话)中。它一定会运行,但如果
				find
				和
				update
				能以某种方法共享一个
				session
				(会话)那才是真正的好。并且,它能更好的避免在
				session
				(会话)周围的凌乱的方法署名。当它运作时,它是难看的,因此我们不想看到下面这样:
		
		
				---------------------------------------------------------------------------------------------
		
		
				
						
								
										
												
Session session 
										=
										 HibernateFactory.openSession();
Event foundEvent 
										=
										 eventDao.find(event.getId(), session);
foundEvent.setDuration(
										30
										);
eventDao.update(foundEvent, session); 
						
				
		
		
				---------------------------------------------------------------------------------------------
		
		
				
						    
				
				给方法增加
				session
				(会话)参数,强制责任,管理和在客户端代码共享
				session
				(会话)。这样会带来重复,复杂和潜在的错误。
		
		
				
						    
				
				这个问题的一个潜在的解决方案是众所周知的
				Thread Local Session
				模式。这个模式将在第八章介绍,因此我们不会在这里直接介绍。我们改用另外一种框架练习,
				spring
				,它使用
				Thread
Local Session
				模式,在下面会有介绍。
		
		
				
						 
				
		
		
				
						7.3 
				
				
						层的父型模式
				
		
		
				
						    
				
				常规的
				J2EE
				智者认为应用程序被划分成不同的层。假设你的应用程序已经有这些层了,当然,依赖于你所读的书。一些普遍的层的选择如下:
		
		
				
				
						n        
				
				
				表示层,这里是所有用户交互和表示的代码。
		
		
				
				
						n        
				
				
				领域层,这里是逻辑的商务代码。
		
		
				
				
						n        
				
				
				持久层,这里是数据存储操作的代码。
		
		
				
						    
				
				不管你的应用程序是否有这些层,在层中的每个对象都有某些共同的代码能够被固定到一个类中,这一点是非常普通的。这个原因出现了层的父型模式,每一层都有“一种类型,这种类型作为所有的层中的类型的父型”2。你能够使用父型模式简化你的
				DAO
				。
		
		
				
						    
				
				Figure7.2
				用一个简单的层次显示了层的父型
				AbstractDao
				,它提供了
				protected
				方法,在子类中可以覆盖和改为
				public
				。
		
		
				
						
						
						 
						
						
						
				
		
		
				
						    
				
				
						Figure 7.2
				
				
				
				层的父型
				AbstractDao
				的图
		
		
				
						    
				
				下一步就是创建
				AbstractDao
				,下一节将介绍。
		
		
				
						 
				
		
		
				
						
								7.3.1
						
				
				
						创建
				
				
						AbstractDao
				
				
						
								
								
						
				
		
		
				
						    
				
				第一步是创建你的父型,
				AbstractDao
				,所有的
				DAO
				最后将扩展。
				Listing
7.2
				显示了类的内容。
		
		
				Listing 7.2
				
				
				层的父型实现,
				AbstractDao
				,它有所有
				DAO
				的共同的业务。
		
		
				-----------------------------------------------------------------------------------------
  package com.manning.hq.ch07;
import org.hibernate.HibernateException;
import org.hibernate.Query;import org.hibernate.Session;
import org.hibernate.Transaction;
import java.util.List;
  
/**
* 层的父型处理所有DAO共同的运作
*/
public abstract class AbstractDao{
    private Session session;
    private Transaction tx;
    public AbstractDao() {
        HibernateFactory.buildIfNeeded();
    }
    protected void saveOrUpdate(Object obj){//运作是普通的,而不是特指域对象
        try {
            startOperation();
            session.saveOrUpdate(obj);
            tx.commit();
        } catch (HibernateException e) {
            handleException(e);
        } finally {
            HibernateFactory.close(session);
        }
    }
    protected void delete(Object obj) {
        try {
            startOperation();
            session.delete(obj);
            tx.commit();
        } catch (HibernateException e) {
            handleException(e);
        } finally {
            HibernateFactory.close(session);
        }
    }
    protected Object find(Class clazz, Long id){//查找基于类和id的持久化对象
        Object obj = null;
        try {
            startOperation();
            obj = session.load(clazz, id);
            tx.commit();
        } catch (HibernateException e) {
            handleException(e);
        } finally {
            HibernateFactory.close(session);
        }
        return obj;
    }
    protected List findAll(Class clazz) {
        List objects = null;
        try {
            startOperation();
            Query query = session.createQuery("from " + clazz.getName());
            objects = query.list();
            tx.commit();
        } catch (HibernateException e) {
            handleException(e);
        } finally {
            HibernateFactory.close(session);
        }
        return objects;
    }
    protected void handleException(HibernateException e)  throws DataAccessLayerException {
        HibernateFactory.rollback(tx);
       throw new DataAccessLayerException(e);
    }
    protected void startOperation() throws HibernateException {
        session = HibernateFactory.openSession();
        tx = session.beginTransaction();
    }
}
				
						
								
								
						
				
		
		
				--------------------------------------------------------------------------------------------
				
						
								
										
    在这个Listing中,你看到了共同的CRUD方法,包括save, find和delete方法都放入AbstractDao类中。他们是
generic和protected,因此子类能够调用它们。这样你的EventDao将简化。这里是一个简单的简化了的方法:
								---------------------------------------------------------------------------------------------
								
public     class   ImprovedEventDao   extends   AbstractDao {
//  其他的方法省略
    public   void  create(Event event)  throws  DataAccessLayerException {
        saveOrUpdate(event);
    }
    public  Event find(Long id)  throws  DataAccessLayerException {
        return  (Event) find(Event. class , id);
    }
}
--------------------------------------------------------------------------------------------
								
    ImprovedEventDao的仅有的责任就是执行业务和委托调用父类。样板代码和潜在的复制的双重问题得到解决。当我们增加一个新的实体对象时,如:Locations或者Speakers,添加新的DAO--使用AbstractDao作为层的父型,将是非常迅速的。
--------------------------------------------------------------------------------------------
				
		
		
				
						
								
								
								
								
								
										
												
												public classImprovedLocationDao extendsAbstractDao {
//其他的方法省略
    publicvoid create(Location location) throws  DataAccessLayerException {
        saveOrUpdate(location);
    }
    publicLocation find(Long id)  throws  DataAccessLayerException {
        return  (Location) find(Location. class , id);
    }
}
										---------------------------------------------------------------------------------------------
										
								
								
								
						
				
				
						
						
				
		
		
				
						
						
				
				通过层的父型的介绍,剩余的问题得到解决,
				DAO
				与游离对象运作。我们想在我们的方法中共享会话,甚至通过不同的
				DAO
				。为了做到这一点,我们将学习一个新的流行框架,
				Spring
				.
		
		
				
						 
				
		
		
				7.4 
				Spring
				框架
		
		
				
						       
				
				我们已经注意到已经定义的
				DAO
				实现中的一些缺陷。复制资源管理代码和使用业务级的
				session
				(
				session per operation
				)使解决方案会比我们需要的更加复杂,而且也没有我们喜欢的灵活。我们一定能过编写更好的更健壮的解决方案。幸运的是,我们不需要担心
				---
				一个优秀的开源解决方案,
				Spring
				框架已经提供给我们了。
				
						
						
				
		
		
				
						       Spring
				解决了比帮助我们解决
				Hibernate
				更多的问题。这是事实,“一个轻量级的容器,允许开发者连接商务对象,
				DAO
				和资源就像
				JDBC DataSources
				和
				Hibernate SessionFactories
				。”
				
						3  
				
				它使用中心
				XML
				配置文件去管理资源,甚至它自身的
				web MVC
				框架(
				Model-View-Controller
				)。
				Spring
				是普通的框架,就是说它可以使用在许多不同的位置中。如果你不熟悉
				Spring
				,你也许会想我该怎样使用它,你也许认为他仅仅是个框架,假设用来提供某种编译。因此我们将在这里展示。
				
						
						
				
		
		
				
						       Spring
				已经被考虑成熟的分割为稳固的集中的若干模块,包括我们先前提到的
				MVC
web
				框架,
				JDBC
				支持,
				aspect-oriented programming
				(
				AOP
				)(
				面向剖面编程
				)和
				ORM
				模块。这样就允许你使用其中你需要的,而不用学习或者考虑其他的。为了我们的目的,我们将仅仅学习怎样简化你的
				Hibernate
				代码,也就是
				ORM
				模块。最佳的开始的地方是模板。
				
						
						
				
		
		
				
						       
				
				首先,你需要获得
				Spring
				框架的副本,你可以在
				
						www.springframework.org
				
				找到。解压到
				applications
				目录下的
				Hibernate
				旁边。
				Spring
				有许多可选择的包,但为了简单,你只需要考虑一个
				JAE
				包,它就是
				applications\spring-framework-1.2-rc2\dist\spring.jar
				文件。将它加入到
				build.xml
				文件的
				classpath
				中。
				
						
						
				
		
		
				-------------------------------------------------------------------------------------------------------------------------
		
		
				
				
				
				<
				property name
				=
				"
				spring.version
				"
				 value
				=
				"
				1.2-rc2
				"
				/>
				
						
				
				<
				property name
				=
				"
				spring.lib.dir
				"
				
						
    value
				=
				"
				${applications.dir}/spring-framework-${spring.version}
				"
				/>
				
						
				
				<
				path id
				=
				"
				spring.lib.path
				"
				>
				
						
				
				<
				fileset dir
				=
				"
				${spring.lib.dir}\dist
				"
				>
				
						
				
				<
				include name
				=
				"
				**/spring.jar
				"
				/>
				
						
				
				</
				fileset
				>
				
						
				
				</
				path
				>
				
						
				
				<
				path id
				=
				"
				runtime.classpath
				"
				>
				
						
				
				//
				 其他的 paths 省略。
				
				
				
						
				
				<
				path refid
				=
				"
				spring.lib.path
				"
				/>
				
						
				
				<
				path
				>
		
		
				
						
								
								
						
				
		
		
				-------------------------------------------------------------------------------------------------------------------------
		
		
				
						       
				
				这个代码配置了
				Spring
				使它能过在我们的示例项目中使用。
				Hibernate3
				最近已经发布(在出版的时候),其他支持项目如
				Spring
				也跟上提供支持了。这里我们使用最新的版本。另外,因为
				Spring
				不得不支持
				Hibernate 2
				和
				Hibernate 3,
				一个新的包,
				org.springframework.orm
				。
				hibernate3
				已经将它加入到
				Hibernate3
				的项目中了。接下来,让我们看看
				Spring
				怎样被使用来简化我们的示例项目。
				
						
						
				
		
		
				
						 
				
		
		
				
						
								7.4.1
						
				
				
						在模板中是什么
				
				?
		
		
				
						    
				
				Spring
				给我们提供了
				Hibernate
				业务的模板。模板有什么,我们为什么需要它?答案就在我们的
				SimpleEventDao
				中的
				create
				方法中。
				
						
						
				
		
		
				--------------------------------------------------------------------------------------------
		
		
				
				
				
				protected
				 
				void
				 create(Event event) {
				    try
				 {
        startOperation();
        session.save (event);
        tx.commit();
    } 
				catch
				 (HibernateException e) {
        handleException(e);
    } 
				finally
				 {
        HibernateFactory.close(session);
    }
}
		
		
				
						
								
								
						
				
		
		
				--------------------------------------------------------------------------------------------
		
		
				
						    
				
				如果你注意了,方法中只调用一个真正的事件是:
				save
				()。其他的每一行,我们喜欢称为“
				excise
				(税)”。
				excise
				(税)是我们为了工作不得不去做的额外的事情,这些事情不是真正的直接重要。它就像当你开车去上班,驾驶的实际行动才是重要的事情;开车库门和倒车都是
				excise
				(税)任务,它可以看成同等重要,也可以忽略或者自动完成。
				
						
						
				
		
		
				
						       
				
				在程序中,
				excise
				(税)是框架或者语言安全需要,你不得不编写的代码。一个典型的
				excise
				(税)例子就是
				Java 
				除去了内存管理。
				Spring 
				能够除去
				Hibernate
				和
				JDBC
				要求之下的资源管理
				excise
				(税)的一部分。
				
						
						
				
		
		
				
						       
				
				一般情况下,当你复制代码,你能够
				refactor
				出
				一个方法或类。这里,因为复制代码是商务方法周围的
				resource 
cleanup
				(资源清理),使它更加复杂。现在有模板可用。导入
				Spring
				提供的类:
				org.springframework.orm.hibernate3.HibernateTemplate
				。它包含了所有资源处理代码以致于你仅只要写一个重要方法就可以了。我们的
				create()
				方法能够这样写:
				
						
						
				
		
		
				----------------------------------------------------------------------------------------------------------------------------------------------------
		
		
				
				
				
				import
				 org.hibernate.Hibernate;
				import
				 org.hibernate.SessionFactory;
				import
				 org.springframework.orm.hibernate3.HibernateTemplate;
				protected
				 
				void
				 create(Event event) {
    SessionFactory sf 
				=
				 HibernateFactory.getSessionFactory();
    HibernateTemplate template 
				=
				 
				new
				 HibernateTemplate(sf);
    template.saveOrUpdate(event);
}
		
		
				
						
								
								
						
				
		
		
				-------------------------------------------------------------------------------------------------------------------------
		
		
				注意我们没有做什么:
				
						
						
				
		
		
				
				
						n        
				
				
				从
				SessionFactory
				获得
				session
		
		
				
				
						n        
				
				
				开始事物
				
						
						
				
		
		
				
				
						n        
				
				
				捕获预期异常和将他转变为非预期异常(
				3.x
				版本不需要,
				2.x
				则需要)
				
						
						
				
		
		
				
				
						n        
				
				
				提交事物
				
						
						
				
		
		
				
				
						n        
				
				
				将改变输入数据库
				
						
						
				
		
		
				
				
						n        
				
				
				关闭
				session
		
		
				这里有许多事情我们不需要担心,因为
				HibernateTemplate
				已经照顾到了。你或许注意到
				HibernateTemplate
				看上去像包裹
				Session
				的周围。实际上,可以把
				HibernateTemplate
				理解为一个“聪明”的
				Session
				,它知道怎样打开,关闭和在运行完清除。在之前默认的情况下,它使用的是方法级事务(
				transaction per method
				)模式。这是非常简单的,但你将在后面看到你也能够改事务的范围。这里有两个基本的方式和
				Hibernatetemplate
				互动:通过
				convenience
mehod
				(便利的方法)和重要的
				callback
				(回调)。
				
				
				
						
						
				
		
		
				
						 
				
		
		
				
						Convenience methods
				
				
						(便利的方法)
				
		
		
				
						    
				
				简单的事情将变得容易。在许多案例中,你想用
				Session
				(会话)做什么是非常重要的:执行保存,更新有力对象,或者运行
				HQL
				查询。没有一个需要礼仪来获得完成。
				HibernateTemplate
				类提供了基本的方法,因此一行代码就可以简单的调用业务。这里有一些方法的简单样例:
		
		
				---------------------------------------------------------------------------------------------
		
		
				
				
				
				import
				 com.manning.hq.ch07.Event;
				import
				 com.manning.hq.ch07.HibernateFactory;
				import
				 org.springframework.orm.hibernate3.HibernateTemplate;
				import
				 java.util.List;
SessionFactory sessionFactory 
				=
				HibernateFactory.getSessionFactory();
				//
				 创建连接 SessionFactory 的模板
				
				
				
						
HibernateTemplate template 
				=
				new
				 HibernateTemplate(sessionFactory);
Event event1 
				=
				 
				new
				 Event();
event1.setName(
				"
				Event 1
				"
				);
Event event2 
				=
				 
				new
				 Event();
event2.setName(
				"
				Event 2
				"
				);
				    try
				 {
        template.save (event1);   
				//
				 在一个事务中保存 event
				
				
				
						
        template.save (event2);
				//
				 加载一个 event
				
				
				
						
        Event obj 
				=
				 (Event) template.load(Event.
				class
				, event1.getId());
        System.out.println(
				"
				Loaded the event
				"
				 
				+
				 obj.getName());
				//
				 找到所有的 event
				
				
				
						
        List events 
				=
				 (List) template.find(
				"
				from Event
				"
				);
        System.out.println(
				"
				# of Events 
				"
				 
				+
				 events.size());
    } 
				finally
				 {
        template.delete(event1); 
				//
				 删除一个 event
				
				
				
						
        template.delete(event2);
    }
		
		
				
						
								
								
						
				
		
		
				---------------------------------------------------------------------------------------------
		
		
				convenience
methods
				(
				便利的方法)是有代表性的正确的命名,就像
				Session
				(会话)中的方法一样。他们能被
				session
				(会话)作为
				one-for-one
				(一对一)复位直接调用,没有任何杂乱的
				resource cleanup
				(资源清除)代码障碍。
		
		
				
						 
				
		
		
				
						Callback
				
				
						(回调)
				
		
		
				
						    
				
				复杂的事情可能有好处。不是所有的在单个
				transaction
				(
				事务)中的单个
				query
				(查询)能够轻松的减少业务。在这些业务中,
				spring
				提供了
				Callback
				接口。它允许你在将要执行的模板中编写
				callback
				方法。例如,如果你想构建一个复杂的
				query
				(查询),更新一些数据,然后保存,所有的都在一个业务中:
		
		
				-------------------------------------------------------------------------------------------
		
		
				
				
				
				import
				 org.hibernate.HibernateException;
				import
				 org.springframework.orm.hibernate3.HibernateCallback;
				import
				 java.sql.SQLException;
				import
				 org.hibernate.Query;
				import
				 java.util.List;
				import
				 java.util.Iterator;
				import
				 com.manning.hq.ch07.Event; 
template.execute(
				new
				 HibernateCallback() {
				    public
				 Object doInHibernate(Session session) 
				throws
				 HibernateException, SQLException {
       Query query 
				=
				 session.createQuery(
				"
				from Event
				"
				);
        query.setMaxResults(
				2
				);
        List events 
				=
				 query.list();
				        for
				 (Iterator it 
				=
				 events.iterator(); it.hasNext();) {
            Event event 
				=
				 (Event) it.next();
            event.setDuration(
				60
				);
        }
				        return
				 
				null
				;
    }
}) ;
		
		
				
						
								
								
						
				
		
		
				---------------------------------------------------------------------------------------------
		
		
				这里,
				Callback
				接口使用了匿名内部类,
				HibernateCallback
				,定义了一个单一的方法,
				doInHibernate()
				。你可以编写方法主体,然后提交
				HibernateCallback
				
				
				对象给模板,然后执行。模板处理资源管理代码,让你只需要编写任务的
				query
				(查询)逻辑。
		
		
				
						 
				
		
		
				
						
								7.4.2
						
				
				
						
						
				
				
						Beans
				
				
						
						
				
				
						和 它们的
				
				
						factories
				
				
						(工厂)
				
		
		
				你已经看到能够程序化使用
				Spring
				去减少
				resource
cleanup
				(资源清除)代码。另外i,它能过更好的组织项目。
				Spring
				的惯例的说法是“轻量级”容器。它胜任执行和配置简单的
				JavaBeans
				。它基本扮演构建和配置你应用程序中的
				beans
				的工厂角色。意思是它能够被使用去配置大多数现存的
				architectures
				(框架)和库,包括
				Hibernate
				。
				
						
						
				
		
		
				
						 
				
		
		
				
						中心的配置文件
				
				
						
								
								
						
				
		
		
				
						    
				
				在这一点上,你将通过组合使用
				hibernate.cfg.xml
				文件(
				declaratively
				(声明性的
))和使用灵活的编程方式,如HibernateFactory来配置Hibernate。Spring提供了另外一个方法整体声明配置Hibernate。使用Spring的最大好处就是你能够减少编程配置需要的元素。
		
				
						 
				
		
		
				Spring
				能够读用一般配置格式编写的
				XML
				文件。
				XML
				指定了怎样连接不同对象,包括
				DataSource
				(数据源),
				SessionFactory
				和所有的
				DAOs
				。一旦你配置了文件,你就能够将它作为查找
				DAOs
				的中心“票据交换所”使用。例如,在
				classpath
				的
				root
				(根部)创建一个叫
				applicationContext.xml
				文件。就像
				listing7.3
				所显示那样。
		
		
				
						 
				
		
		
				
						listing7.3 ApplicationContext.xml
				
				
						,定义了
				
				
						DataSource
				
				
						(数据源),
				
				
						SessionFactory
				
				
						和
				
				
						DAO
				
		
		
				-------------------------------------------------------------------------------
		
		
				
				  
				<?
				xml version
				=
				"
				1.0
				"
				 encoding
				=
				"
				UTF-8
				"
				?>
				
						
						
				
				  <!
				DOCTYPE beans PUBLIC
				      "
				-//SPRING//DTD BEAN//EN
				"
				
						
						
				
				      "
				http://www.springframework.org/dtd/spring-beans.dtd
				"
				>
				
						
				
				
						
    <
				beans
				>
				
						
				
				        <
				bean id
				=
				"
				dataSource
				"
				
				
				 class
				=
				"
				org.apache.commons.dbcp.BasicDataSource
				"
				           destroy
				-
				method
				=
				"
				close
				"
				>
				   ①
				        <
				property name
				=
				"
				driverClassName
				"
				>
				
						
				
				            <
				value
				>
				com.mysql.jdbc.Driver
				</
				value
				>
				
						
				
				        </
				property
				>
				
						
				
				        <
				property name
				=
				"
				url
				"
				>
				
						
				
				            <
				value
				>
				jdbc:mysql:
				//
				localhost/events_calendar</value>
				
				
				
						
				
				        </
				property
				>
				
						
				
				        <
				property name
				=
				"
				username
				"
				>
				
						
				
				            <
				value
				>
				root
				</
				value
				>
				
						
				
				        </
				property
				>
				
						
				
				        <
				property name
				=
				"
				password
				"
				>
				
						
				
				            <
				value
				></
				value
				>
				
						
				
				        </
				property
				>
				
						
				
				        </
				bean
				>
				
						
						
				
				        <
				bean id
				=
				"
				factory
				"
				
				
				 class
				=
				
				
				"
				org.springframework.orm.hibernate3.LocalSessionFactoryBean
				"
				>
				 ②
				        <
				property name
				=
				"
				mappingResources
				"
				>
				
						
				
				            <
				list
				>
				
						
				
				                <
				value
				>
				com
				/
				manning
				/
				hq
				/
				ch07
				/
				Event.hbm.xml
				</
				value
				>
				
						
				
				                <
				value
				>
				com
				/
				manning
				/
				hq
				/
				ch07
				/
				Location.hbm.xml
				</
				value
				>
				
						
				
				            </
				list
				>
				
						
				
				        </
				property
				>
				
						
				
				        <
				property name
				=
				"
				hibernateProperties
				"
				>
				
						
				
				            <
				props
				>
				
						
				
				                <
				prop key
				=
				"
				hibernate.dialect
				"
				>
				org.hibernate.dialect.MySQLDialect
				</
				prop
				>
				
						
				
				                <
				prop key
				=
				"
				hibernate.show_sql
				"
				>
				false
				</
				prop
				>
				
						
				
				            </
				props
				>
				
						
				
				        </
				property
				>
				
						
				
				        <
				property name
				=
				"
				dataSource
				"
				>
				   ③
				            <
				ref bean
				=
				"
				dataSource
				"
				/>
				
						
				
				        </
				property
				>
				
						
				
				        </
				bean
				>
				
						
						
				
				        <
				bean id
				=
				"
				eventDao
				"
				
				
				class
				=
				"
				com.manning.hq.ch07.EventSpringDao
				"
				>
				    ④
				        <
				property name
				=
				"
				sessionFactory
				"
				>
				     ⑤
				            <
				ref bean
				=
				"
				factory
				"
				 
				/>
				
						
				
				        </
				property
				>
				
						
				
				        </
				bean
				>
				
						
				
				    </
				beans
				>
		
		
				
						
								
								
						
				
		
		
				-------------------------------------------------------------------------------
		
		
				listing7.3
				解释
				
						
						
				
		
		
				①
				
						    
				
				配置一个基本的数据源,它使用由
				Hibernate
				发布的
				Apache Commons database connection
pool (DBCP)
				。
				
						
						
				
		
		
				
				
						②      
				
				
				配置一个
				SessionFactory
				,构建在
				Spring
				
				
				SessionFactory 
				wrapper, LocalSessionFactoryBean
				。当
				Spring
				读取这个文件时,它就构建一个
				SessionFactory
				。
				SessionFactory
				存储在
				Key factory
				。
				
						
						
				
		
		
				
				
						③       
				
				
				连接
				SessionFactory
				和数据源。
				
						
						
				
		
		
				
				
						④       
				
				
				配置你的
				EventSpringDao
				和
				eventDao
				。
				
						
						
				
		
		
				
				
						⑤       
				
				
				连接
				DAO
				和
				session factory
				。他允许
				DAO
				打开
				session
				和发布
				queries
				。
				
						
						
				
		
		
				-------------------------------------------------------------------------------------------------------------------------
		
		
				Listing 7.3 
				中
				XML
				配置文件列举了所有能够经常改变详细内容。它完成了许多与
				hibernate.cfg.xml
				所作的相同的事情,也为我们构建了
				SessionFactory
				,这一点将在下一节看到。
				
						
						
				
		
		
				
						 
				
		
		
				
						构建
				
				
						AppicationContext
				
				
						
								
								
						
				
		
		
				
						    
				
				你刚刚创建的
				applicationContext.xml
				详细的描述了怎样构建
				session
				工厂。它基本上可以一对一的替换你所看到的
				HibernateFactory
				使用的
				hibernate.cfg.xml
				。它定义了通常在
				hibernate.cfg.xml
				中的属性和映射文件。在我们先前的示例代码中,你需要构建
				SessionFactory
				,或者通过你的
				
EventDao
				对象连接
				SessionFactory
				。
				Spring
				颠覆了这个概念。
				Spring
				为你构建了
				EventDao
				,你需要询问
				EventDao
				的首选项,就像:
				
						
						
				
		
		
				---------------------------------------------------------------------------------------------
		
		
				
				
				
				import
				 org.springframework.context.support.ClassPathXmlApplicationContext;
				import
				 com.manning.hq.ch07.Event;
ClassPathXmlApplicationContext ctx 
				=
				 
				new
				
						
ClassPathXmlApplicationContext(
				"
				applicationContext.xml
				"
				);
EventSpringDao eventDao 
				=
				(EventSpringDao) ctx.getBean(
				"
				eventDao
				"
				, EventSpringDao.
				class
				);
Event event 
				=
				 
				new
				 Event();
eventDao.saveOrUpdate(event);
		
		
				
						
						
				
		
		--------------------------------------------------------------------------------------------
		
		
		
				ClasspathXmlApplicationContext
				看上去
				在
				classpath
				中,因为配置文件的名字在
				instruction
				中已提供(
				The 
				ClasspathXmlApplicationContext 
				looks in the classpath for the name of the
configuration file provided in the instructions.
				)在这个案例中,
				applicationContext.xml
				在
				classpath
				的
				root
				(根)。你能够从
				application context
				通过名字请求
				bean
				。
				getBean
				()方法有两个参数:
				bean
				的名字(
				eventDao
				),你期望的类的类型(
				EventSpringDao
				)。
				
						
						
				
		
		
				在此之下,
				Spring
				构建了
				SessionFactory
				并将所有的
				Bean
				连接在一起。我们更早的认识到
				Spring
				与
				Javabean
				一起工作。所有的在
				applicationContext.xml
				文件中的
				<bean>
				元素都需要
				JavaBean
				。这包括了象下面的
				EventSpringDao
				。
				
						
						
				
		
		
				-------------------------------------------------------------------------------------------------------------------------
		
		
				
				
				
				public
				 
				class
				 EventSpringDao 
				extends
				 AbstractSpringDao{
				    public
				 EventSpringDao(){}
				    public
				 Event find(Long id){
				        return
				 (Event) 
				super
				.find(Event.
				class
				, id);
    }
				    //
				 Other methods excluded
				
				
				
						
}
				
						
						
				
				
		
		
				----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
		
		
				
						         
				
				另外更早的认识到的好处是,
				Spring
				提供了
				
						org.springframework.orm.hibernate3.support.HibernateDaoSupport
				
				
						,
				
				应用
				Dao
				层的父型。她管理了
				SessionFactory
				和一些有用的方法去处理
				Session
				,
				Logging
				和
				HibernateTemplate
				。这有这些方法的示例:
		
		
				-------------------------------------------------------------------------------
		
		
				
				public
				 
				abstract
				 
				class
				 HibernateDaoSupport 
				implements
				 InitializingBean {
				    protected
				 
				final
				 Log logger;
				    private
				 HibernateTemplate hibernateTemplate;
				    public
				 
				final
				 
				void
				 setSessionFactory(SessionFactory sessionFactory);
				    public
				 
				final
				 SessionFactory getSessionFactory();
				    public
				 
				final
				 
				void
				 setHibernateTemplate(HibernateTemplate hibernateTemplate);
				    public
				 
				final
				 HibernateTemplate getHibernateTemplate();
				                                               protected
				 
				final
				 Session getSession() 
				throws      DataAccessResourceFailureException, IllegalStateException;
    protected final void closeSessionIfNecessary(Session session);
}
		
				-----------------------------------------------------------------------------------
		
		
				他提供了一些基本的方法,但我们选择重写
				HibernateDaoSupport
				对象,为了
提供更多的便利方法。
				Listing7.4
				显示了改变的类。
		
		
				
						Listing
7.4 
				
				
						你的应用的层的父型
				
				
						 DAOs
				
				
						
						
				
		
		
				--------------------------------------------------------------------------------------------
		
		
				
				
				
				package
				 com.manning.hq.ch07;
				import
				 java.util.List;
				import
				 org.springframework.orm.hibernate3.support.HibernateDaoSupport;
				public
				 
				abstract
				 
				class
				 AbstractSpringDao 
				extends
				 HibernateDaoSupport{
				    public
				 AbstractSpringDao() { }
				    protected
				 
				void
				 saveOrUpdate(Object obj) {
        getHibernateTemplate().saveOrUpdate(obj);
    }
				    protected
				 
				void
				 delete(Object obj) {
        getHibernateTemplate().delete(obj);
    }
				    protected
				 Object find(Class clazz, Long id) {
				        return
				 getHibernateTemplate().load(clazz, id);
    }
				    protected
				 List findAll(Class clazz) {
				        return
				 getHibernateTemplate().find(
				"
				from 
				"
				 
				+
				 clazz.getName());
    }
}
		
		
		
				
						
								
								
						
				
		
		
				------------------------------------------------------------------
		
		
				重点注意的是
				AbstractSpringDao
				使用它的父类
				sessionFactory
				成员。
				HibernateDaoSupport
				提供了
				getter
				和
				setter
				方法,
				Spring
				使用
				setter
				方法去连接
				SessionFactory
				。从
				applicationContext
				.xml
				文件中调用这些行:
		
		
				-------------------------------------------------------------------------------
		
		
				
				
				
				<
				bean id
				=
				"
				eventDao
				"
				 
				class
				=
				"
				com.manning.hq.ch07.EventSpringDao>
				
				
				
						
				
				    <
				property name
				=
				"
				sessionFactory
				"
				>
				
						
				
				        <
				ref bean
				=
				"
				factory
				"
				 
				/>
				
						
				
				    </
				property
				>
				
						
				
				</
				bean
				>
		
		
		
				
						
								
								
						
				
		
		
				------------------------------------------------------------------
		
		
				这是调用
				setSessionFactory
				()
				的片断,通过我们配置的
				SessionFactory
				,我们叫它为工厂。你所看到的
				AbstractSpringDao
				是由
				AbstractDao
				进化而来,你可以从
				find()
				方法中完整的除去大多数资源管理代码。
				HibernateTemplate
				和
				HibernateDaoSupport
				替代了被控制的一切。
		
		
				
						 
				
		
		
				
						创建注册(
				
				
						Creating a registry
				
				
						) 
				
		
		
				我们最终是为了将所有集中到一起并创建中心的注册,开发者能够使用它直接获得参数给
				DAO
				和
				SessionFactory
				。通过单一的类,
				CalendarRegistry
				,你能确保将来开发有一个显示的,单一的,强壮类型的类来使用,不需要知道类的详细内部机制。
				Figure 7.3
				显示了怎样将所有集中到一起。
				
						
						
				
		
		
				使用
				Spring
				,你获得了配置的好处,允许你轻松的交换数据资源,数据库和添加新的对象成员。
				Listing7.5
				就是
				CalendarRegistry
				。
				
						
						
				
		
		
				
						
						
						 
						
						
						
				
		
		
				
						 
				
		
		
				Figure
7.3 CalendarRegistry
				图表,获得参数到
				EventDao
		
		
				
						 
				
		
		
				
						Listing
7.5 
				
				
						CalendarRegistry
				
				
						, 
				
				
						组织
				
				
						Dao
				
				
						的中心的类
				
				
						
						
				
		
		
				-------------------------------------------------------------------------------------------------------------------------
		
		
				
				package
				 com.manning.hq.ch07;
				import
				 org.springframework.context.ApplicationContext;
				import
				 org.springframework.context.support.ClassPathXmlApplicationContext;
				import
				 org.hibernate.SessionFactory;
				public
				 
				class
				 CalendarRegistry {
				    private
				 
				static
				 ApplicationContext ctx;
				    static
				 {
        ctx 
				=
				 
				new
				 ClassPathXmlApplicationContext(
				"
				applicationContext.xml
				"
				);
    }
				    private
				 CalendarRegistry() {}
				    public
				 
				static
				 SessionFactory getSessionFactory() {
				        return
				 (SessionFactory) ctx.getBean(
				"
				factory
				"
				, SessionFactory.
				class
				);
    }
				    public
				 
				static
				 EventSpringDao getEventDao() {
				        return
				 (EventSpringDao)ctx.getBean(
				"
				eventDao
				"
				, EventSpringDao.
				class
				);
    }
}
		
		
		
				
						
								
								
						
				
		
		
				-------------------------------------------------------------------------------------------------------------------------
		
		
				正如你所见,
				CalendarRegistry
				是单例模式,但是因为它背后是
				Spring
				,你能够轻松的实现底层的交换。它从
				classpath
				中装载单一的静态的
				ApplicationContext
				,然后使用它获取参数。现在客户端对象能够在项目中任何地方获得参数给
				EventDao
				,不需要知道关于
				Spring
				做了什么。
				
						
						
				
		
		
				-------------------------------------------------------------------------------------------------------------------------
		
		
				
				EventSpringDao eventDao 
				=
				 CalendarRegistry.getEventDao();
eventDao.saveOrUpdate(event);
		
		
				
						
						
				
				--------------------------------------------------------------------------------------------
		
		
				
						 
				
		
		
				
						更多的
				
				
						Spring
				
				
						工具
				
		
		
				就像你所见,使用
				Spring
				能够最大限度的简化
				Hibernate
				的资源管理代码。我们显示了两个你能够使用的包含的级别。
				HibernateTemplate
				能够被嵌入你的
				DAO
				中,或者使用
				Spring
				的轻量级容器去管理
				DAO
				。
		
		
				
						    
				
				Spring is a fairly straightforward framework, but we haven’t scratched the
surface of what it can do here.
				(
				Spring
				还算一个直接的框架,但我们没有就它能在这做什么过多的纠缠)
				Spring
				也支持事务
				API
				管理框架,
				AOP
				框架,一个
				RuntimeException
				框架,能够拦截数据库发出的大多数迟钝的
				SQLException
				,将它转变成更显而易见和包罗万象的
				exception
				。更多的信息,请查看实在又全面的
				Spring
				文档。
				
						
						
				
		
		
				
						 
				
		
		
				
						7.5
				
				
						 总结
				
				
						
						
				
		
		
				这一章的焦点在于提高组织你的应用程序代码。我们集中了
				HQL
				,使用了
				DAO
				模式。我们通过加入其它的模式更提高了初始实现,层的父型,它允许增加更多的DAO,不需要复制过多的代码到项目中新添加的对象成员。
		
		
				
						    
				
				这一章也探索了怎样使用
				Spring
				,另一个流行的开源项目,管理
				Hibernate
				需要的
				boilerplate
				(样板)资源管理代码。
				Spring
				提供了标题选项,
				HibernateTemplate
				,
				pluggable
				,
				ApplicationContext
				。增加一个
				CalendarRegistry
				,
				它提供了方法使用
				Spring
				获得项目中的参数,不再需要去包含一个“单块集成电路”了。
		
		
				
						 
				
		
		
				1 
				Hibernate
				如此优秀,为什么还要用别的?在现实中,转变
				ORM
				实现并不是微不足道的,
				DAO
				是容易产生漏洞的,提取那样做的话就会有问题,将不能从应用程序中完全隐藏
				Hibernate
				。(
				DAOs are leaky enough
abstractions that doing so probably won’t completely hide Hibernate from the
application.
				)。
				因此不需要放太多的精力去密封
				DAO
				层,在以后为了可能的某种目的要转变
				ORM
				实现。
		
		
				
						 
				
		
		
				2 
				选自
				《
				Patterns
of Enterprise Application Architecture
				》
				,
				作者:
				Martin Fowler(Addision-Wesley
				专家,
				2003
				)
		
		
				
						 
				
		
		
				3 
				选自在线文章“
				Data
Access with Spring Framework
				”,作者:
				Juergen Hoeller
				,
				2003
				年
				7
				月;
				
						http://hibernate.bluemars.net/110.html
				
				。
				
						
						
				
		
	posted on 2005-12-21 22:21 
千山鸟飞绝 阅读(10539) 
评论(6)  编辑  收藏  所属分类: 
Hibernate