`
gao_20022002
  • 浏览: 160287 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

Spring整理记录之中间层访问

阅读更多

传统上,J2EE开发者有两个事务管理的选择: 全局 或 本地 事务。全局事务由应用服务器管理,使用JTA。局部事务是和资源相关的,比如一个和JDBC连接关联的事务。
全局事务:JTA通常只在应用服务器的环境中才能使用。
本地事务:明显的缺点:它们不能用于多个事务性资源。另一个缺点是局部事务趋向于入侵式的编程模型。
Spring解决了这些问题。它使应用开发者能够使用在 任何环境 下使用 一致 的编程模型。提供声明式和编程式事务管理。
Spring框架对事务管理的支持极大地改变了传统上认为J2EE应用需要应用服务器的认识。
事务管理究竟是否需要应用服务器?什么意思?你理解的事务概念呢?使用Spring,你可以选择何时把你的应用迁移到全功能的应用服务器。用硬编码去实现本地事务来替代EJB CMT或JTA,处理JDBC连接,或者还需要使用硬编码来处理那些全局的、受到容器管理的事务,这样的日子将一去不复返了。使用Spring,你仅需要改动配置文件,而不必改动你的代码。
Spring事务抽象的关键是事务策略的概念。这个概念由org.springframework.transaction.PlatformTransactionManager接口。它是一个SPI接口。它可以很容易地被模拟和桩化。
TransactionDefinition接口指定:事务隔离、事务传播、事务超时、只读状态。数据库事务的四个特性:原子性、一致性、隔离性、持久性。
TransactionStatus 接口为处理事务的代码提供一个简单的控制事务执行和查询事务状态的方法。
JTA是全局事务,可以简单地使用 JtaTransactionManager 来处理Hibernate事务和JTA事务,就像我们处理JDBC,或者任何其它的资源策略一样。
<bean id="txManager" class="org.springframework.transaction.jta.JtaTransactionManager"/>注意任何资源的JTA配置都是这样的,因为它们都是全局事务,可以支持任何事务性资源。
使用Hibernate局部事务,需要定义一个Hibernate的 LocalSessionFactoryBean,应用程序从中获取到Hibernate Session 实例。
不同的事务管理器是如何创建的,以及它们如何被连接到相应的需要被同步到事务的资源上??明白了。
如何直接或间接地使用一种持久化API(JDBC、Hibernate、JDO等)的应用代码,如何确保通过相关的 PlatformTransactionManager 来恰当地获取并操作资源,来满足事务同步,这些操作包括:创建、复用、清理 和 触发(可能没有)。
1、高层次方案:模板 方法,包括 JdbcTemplate、HibernateTemplate和JdoTemplate类。
2、低层次方案:直接同原始持久化API特有的资源类型打交道,包括DataSourceUtils(针对JDBC),SessionFactoryUtils(针对Hibernate),PersistenceManagerFactoryUtils(针对JDO)等等。这些类确保应用代码获取到正确的Spring框架所管理的bean,事务被正确同步,处理过程中的异常被映射到一致的API。
3、TransactionAwareDataSourceProxy:工作在最底层的。这是一个对目标 DataSource 的代理,它包装了目标 DataSource,提供对Spring管理事务的可知性。
Spring的声明式事务管理是通过Spring AOP实现的。
回滚规则的概念比较重要:它使我们能够指定什么样的异常(和throwable)将导致自动回滚。对EJB来说,默认的行为是EJB容器在遇到 系统异常(通常指运行时异常)时自动回滚当前事务。 默认式Spring处理声明式事务管理的规则遵守EJB习惯(只在遇到unchecked exceptions时自动回滚),但通常定制这条规则会更有用。
Spring的事务管理是通过AOP代理实现的。 其中的事务通知由元数据(目前基于XML或注解)驱动。 代理对象与事务元数据结合产生了一个AOP代理,它使用一个PlatformTransactionManager 实现品配合TransactionInterceptor,在方法调用前后实施事务。
我们要把一个服务对象('fooService' bean)做成事务性的。 我们想施加的事务语义封装在<tx:advice/>定义中(其中的 'transaction-manager' 属性被设置为一个指向 PlatformTransactionManager bean的名字, 该bean将会真正管理事务)。配置中最后一段是 <aop:config/> 的定义, 它确保由 'txAdvice' bean定义的事务通知在应用中合适的点被执行(首先我们定义了 一个切面,然后我们用一个通知器(advisor)把这个切面与 'txAdvice' 绑定在一起)。
上面的配置将为'fooService' bean创建一个代理对象,这个代理对象被装配了事务通知,所以当它的相应方法被调用时,一个事务将被启动、挂起、被标记为只读,或者其它(根据该方法所配置的事务语义)。
<aop:pointcut/> 元素定义是AspectJ的切面表示法。
使用一个简单的声明式配置来控制事务的回滚:推荐做法是在Spring框架的事务架构里指出当context的事务里的代码抛出 Exception 时事务进行回滚。请注意Spring框架的事务基础架构代码将默认地只在抛出运行时和unchecked exceptions时才标识事务回滚。 也就是说,当抛出一个 RuntimeException 或其子类例的实例时。(Errors 也一样 - 默认地 - 标识事务回滚。)从事务方法中抛出的Checked exceptions将不被标识进行事务回滚。
什么叫做unchecked exceptions???
在Spring中,你可以通过分别定义特定的 <aop:advisor/> 元素, 让每个advisor采用不同的 'pointcut' 和 'advice-ref' 属性,来达到目的。
<tx:advice/> 有关的设置:事务生成策略。1、事务传播设置 是 REQUIRED;2、隔离级别是DEFAULT;3、事务是 读/写;4、事务超时默认是依赖于事务系统的,或者事务超时没有被支持;5、任何 RuntimeException 将触发事务回滚,但是任何 checked Exception 将不触发事务回滚。
声明式配置事务以及注解式配置。
在由Spring管理的事务中,请记住 物理 和 逻辑 事务存在的差异, 以及传播设置是如何影响到这些差异的。
当事务传播被设置PROPAGATION_REQUIRED的时候, 会为每一个被应用到的方法创建一个逻辑事务作用域。 每一个这样的逻辑事务作用域都可以自主地决定rollback-only状态,当这样的逻辑事务作用域被外部的一个逻辑事务作用域所包含的时候, 他们在逻辑上是独立的。当然了,对于正常的 PROPAGATION_REQUIRED设置来说,他会被映射到相同的物理事务上。 所以一个标记有rollback-only的内部逻辑事务作用域的确会影响到外部的逻辑事务作用域。
PROPAGATION_REQUIRES_NEW,与之前相反,为每一个相关的事务作用域使用了一个完全 独立的事务。在这种情况下,物理事务也将是不同的,因此外部事务可以不受内部事务回滚状态的影响独立提交或者回滚。
PROPAGATION_NESTED 是一个完全不同的设置。它使用了一个单独的物理事务, 这个事务拥有多个可以回滚的保存点。这样部分回滚允许内部事务在它的作用域内触发一个回滚, 并且外部事务能够不受影响的继续。 这通常是对应于JDBC的保存点,所以只会在 JDBC 资源事务管理上起效。
如何同时执行事务性通知(advice)和一些基本的剖析(profiling)通知??在<tx:annotation-driven/>环境中该怎么做?
Spring提供两种方式的编程式事务管理:使用 TransactionTemplate,直接使用一个 PlatformTransactionManager 实现。
TransactionTemplate 采用与Spring中别的 模板 同样的方法, 如 JdbcTemplate 。它使用回调机制,将应用代码从样板式的资源获取和释放代码中解放出来, 这样写出的代码是目的驱动的,把精力集中在开发者想要做的事情上。
TransactionTemplate 类的实例是线程安全的,任何状态都不会被保存。 TransactionTemplate 实例 的确会 维护配置状态,所以当一些类选择共享一个单独的 TransactionTemplate实例时, 如果一个类需要使用不同配置的TransactionTemplate(比如,不同的隔离等级), 那就需要创建和使用两个不同的TransactionTemplate。
使用 org.springframework.transaction.PlatformTransactionManager 来直接管理你的事务。只需通过bean的引用,简单的把你在使用的PlatformTransactionManager 传递给你的bean。 然后,使用TransactionDefinition和TransactionStatus对象, 你可以启动,回滚和提交事务。
Spring提供的DAO(数据访问对象)支持目的是便于以一致的方式使用不同的数据访问技术, 如JDBC,Hibernate或者JDO等。它不仅可以让你方便地在这些持久化技术间切换, 而且让你在编码的时候不用考虑处理各种技术中特定的异常。
Spring提供了一种方便的方法,把特定于某种技术的异常,如SQLException, 转化为自己的异常,这种异常属于以DataAccessException 为根的异常层次。
一致的DAO支持抽象类:JdbcDaoSupport 、HibernateDaoSupport 、JdoDaoSupport 、JpaDaoSupport 。

Spring JDBC抽象框架所带来的价值将在以下几个方面得以体现:1、定义数据库连接参数;2、打开数据库连接;3、声明SQL语句;4、预编译并执行SQL语句;5、遍历查询结果(如果需要的话);6、处理每一次遍历操作;7、处理抛出的任何异常;8、处理事务;9、关闭数据库连接(注:使用了Spring JDBC抽象框架之后,应用开发人员只需要完成声明SQL语句以及处理每一次遍历操作。)
工作模式:JdbcTemplate\NamedParameterJdbcTemplate\SimpleJdbcTemplate\SimpleJdbcInsert 和 SimpleJdbcCall\RDBMS 对象包括MappingSqlQuery, SqlUpdate and StoredProcedure.
JdbcTemplate是core包的核心类。它替我们完成了资源的创建以及释放工作,从而简化了我们对JDBC的使用。 它还可以帮助我们避免一些常见的错误,比如忘记关闭数据库连接。 JdbcTemplate将完成JDBC核心处理流程,比如SQL语句的创建、执行,而把SQL语句的生成以及查询结果的提取工作留给我们的应用代码。 它可以完成SQL查询、更新以及调用存储过程,可以对ResultSet进行遍历并加以提取。 它还可以捕获JDBC异常并将其转换成org.springframework.dao包中定义的,通用的,信息更丰富的异常。
JdbcTemplate类的实例是线程安全的实例。这一点非常重要,正因为如此,你可以配置一个简单的JdbcTemplate实例,并将这个“共享的”、“安全的”实例注入到不同的DAO类中去。 另外, JdbcTemplate 是有状态的,因为他所维护的DataSource 实例是有状态的,但是这种状态是无法变化的。
一旦JdbcTemplate被创建,他是一个线程安全的对象。 一个你需要创建多次JdbcTemplate实例的理由可能在于,你的应用需要访问多个不同的数据库,从而需要不同的DataSources来创建不同的JdbcTemplates实例。
private JdbcTemplate jdbcTemplate;
public void setDataSource(DataSource dataSource) {
  this.jdbcTemplate = new JdbcTemplate(dataSource);
}
NamedParameterJdbcTemplate类为JDBC操作增加了命名参数的特性支持,而不是传统的使用('?')作为参数的占位符。NamedParameterJdbcTemplate类对JdbcTemplate类进行了封装, 在底层,JdbcTemplate完成了多数的工作。
SimpleJdbcTemplate类是对JdbcTemplate类进行的封装,从而可以充分利用Java 5所带来的varargs和autoboxing等特性。
为了从数据库中取得数据,我们首先需要获取一个数据库连接。Spring通过DataSource对象来完成这个工作。
DataSource接口:DataSource是JDBC规范的一部分,它被视为一个通用的数据库连接工厂。通过使用DataSource, Container或Framework可以将连接池以及事务管理的细节从应用代码中分离出来。
使用DriverManagerDataSource和你以前获取一个JDBC连接 的做法没什么两样。你首先必须指定JDBC驱动程序的全限定名,这样DriverManager 才能加载JDBC驱动类,接着你必须提供一个url(因JDBC驱动而异,为了保证设置正确请参考相关JDBC驱动的文档), 最后你必须提供一个用户连接数据库的用户名和密码。
SQLExceptionTranslator接口:如果你需要在 SQLException和org.springframework.dao.DataAccessException之间作转换,那么必须实现该接口。
控制数据库连接??什么意思???
JDBC批量操作:JdbcTemplate的批量操作特性需要实现特定的接口BatchPreparedStatementSetter来进行的;SimpleJdbcTemplate类提供了另外一种批量操作的方式。无需实现一个特定的接口,你只需要提供所有在调用过程中要用到的参数,框架会遍历这些参数值,并使用内置的prepared statement类进行批量操作。
用SimpleJdbc类简化JDBC操作。
用Java对象来表达JDBC操作。
参数和数据处理的基本原则:什么意思??处理BLOB 和 CLOB对象(较大的二进制对象被称之为BLOB类型,而对应的大文本对象被称之为CLOB对象)。处理复杂类型的存储过程调用

Spring Framework在资源管理,DAO实现支持以及事务策略等方面提供了与 Hibernate、JDO、Oracle TopLink、iBATIS SQL Mappings 以及 JPA 的集成。通常来说有两种不同的整合风格:你可以使用Spring提供的DAO模板,或者直接使用Hibernate/JDO/TopLink等工具的原生API编写DAO。无论采取哪种风格,这些DAO都可以通过IoC进行配置,并参与到Spring的资源和事务管理中去。
使用Spring Framework构建你的O/R Mapping DAO的好处包括:便于测试、通用数据访问异常封装、通用的资源管理、完整的事务管理。
资源管理:业务逻辑不再依赖于特定的数据访问与事务策略;不再有硬编码的资源查找、不再有难以替换的singletons、不再有用户自定义的服务注册。 Spring提供了一个简单且稳固的方案使得各种应用逻辑对象连接在一起,使这些对象可重用,并尽可能不依赖容器。所有的数据访问技术都能独立使用,但是他们在Spring提供的基于XML配置且无需依赖Spring的普通JavaBean下会与application Context整合的更好。
在典型的Spring应用程序中,很多重要的对象都是JavaBeans:数据访问template、数据访问对象(使用template)、事务管理器、业务逻辑对象(使用数据访问对象和事务管理器)、web视图解析器、web控制器(使用业务服务)等等。
在Spring容器中创建 SessionFactory:Spring允许你在Spring容器中以bean的方式定义诸如JDBC DataSource或者Hibernate SessionFactory 的数据访问资源。任何需要进行资源访问的应用程序对象只需要持有这些事先定义好的实例的引用。
The HibernateTemplate:对于特定的数据访问对象或业务对象的方法,没有任何实现特定接口的约束,仅仅要求提供一个Hibernate SessionFactory。 一个回调实现能够有效地在任何Hibernate数据访问中使用。HibernateTemplate 会确保当前Hibernate的 Session 实例的正确打开和关闭,并直接参与到事务管理中去。Template实例不仅是线程安全的,同时它也是可重用的。因而他们可以作为外部对象的实例变量而被持有。对于那些简单的诸如find、load、saveOrUpdate或者delete操作的调用,HibernateTemplate 提供可选择的快捷函数来替换这种回调的实现。 不仅如此,Spring还提供了一个简便的 HibernateDaoSupport 基类,这个类提供了 setSessionFactory(..) 方法来接受一个 SessionFactory 对象,同时提供了 getSessionFactory() 和 getHibernateTemplate() 方法给子类使用。
不使用回调的基于Spring的DAO实现:作为不使用Spring的 HibernateTemplate 来实现DAO的替代解决方案,你依然可以用传统的编程风格来编写你的数据访问代码。无需将你的Hibernate访问代码包装在一个回调中,只需符合Spring的通用的 DataAccessException 异常体系。这种直接使用Hibernate访问代码的好处在于它允许你在数据访问代码中抛出 任何 checked exception,而 HibernateTemplate 却受限于回调中的unchecked exception。
HibernateDaoSupport:Spring还提供了一个简便的 HibernateDaoSupport 基类,这个类提供了 setSessionFactory(..) 方法来接受一个 SessionFactory 对象,同时提供了 getSessionFactory() 和 getHibernateTemplate() 方法给子类使用。  HibernateDaoSupport 基类提供了访问与当前事务绑定的 Session 对象的函数,能保证在这种情况下异常的正确转化。
基于Hibernate3的原生API实现DAO:Hibernate3 引入了一个新的特性:“带上下文环境的Session”。 这一特性使得Hibernate自身具备了每个事务绑定当前 Session 对象的功能。
编程式的事务划分:我们可以在这些低层次的数据访问服务之上的应用程序进行更高层次的事务划分,从而让事务能够横跨多个操作。 这里对于相关的业务逻辑对象同样没有实现接口的限制,它只需要一个Spring的 PlatformTransactionManager。 同SessionFactory一样,它可以来自任何地方,但是最好是一个经由 setTransactionManager(..) 方法注入的bean的引用。
声明式的事务划分:作为可选方案,我们可以使用Spring声明式的事务支持。声明式的事务支持通过配置Spring容器中的AOP Transaction Interceptor来替换事务划分的硬编码。 这将使你可以从每个业务方法中重复的事务划分代码中解放出来,真正专注于为你的应用添加有价值的业务逻辑代码。此外,类似传播行为和隔离级别等事务语义能够在配置文件中改变,而不会影响具体的业务对象实现。
事务管理策略:TransactionTemplate 和 TransactionInterceptor 都将真正的事务处理委托给一个 PlatformTransactionManager 实例来处理。
容器资源 vs 本地资源:Spring的资源管理允许你简单地在一个JNDI的 SessionFactory 和一个本地的 SessionFactory 之间切换而无需更改任何一行应用程序代码。Spring对事务管理的支持有一个非常重要的好处:它不依赖于任何容器。
事务管理:将事务管理纳入到Service操作的执行中,你可以使用Spring通用的声明式的事务管理功能。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics