SessionFactory 抽象层
TopLink本身并没有提供SessionFactory抽象层逻辑,多线程的数据访问是建立在中央 ServerSession 上的。对于单线程访问, 这个中央 ServerSession 会为它一个 ClientSession 的实例供其使用。为了提供灵活便捷的创建选项, Spring为TopLink定义了一个 SessionFactory 接口, 从而使你可以任意地在不同的 Session 创建策略之间进行切换。
作为一个一站式的商店,Spring提供了一个 LocalSessionFactoryBean 类, 允许你以bean风格的配置方式来定义一个TopLink的 SessionFactory。 需要进行配置的地方主要是TopLink session配置文件,通常来说还需配置一个受到Spring管理的JDBC DataSource。
<beans>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${jdbc.driverClassName}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<bean id="mySessionFactory" class="org.springframework.orm.toplink.LocalSessionFactoryBean">
<property name="configLocation" value="toplink-sessions.xml"/>
<property name="dataSource" ref="dataSource"/>
</bean>
</beans>
<toplink-configuration>
<session>
<name>Session</name>
<project-xml>toplink-mappings.xml</project-xml>
<session-type>
<server-session/>
</session-type>
<enable-logging>true</enable-logging>
<logging-options/>
</session>
</toplink-configuration>
通常情况下,LocalSessionFactoryBean 在底层将持有一个多线程的TopLink ServerSession 并创建合适的客户端 Session: 它或者是一个普通的 Session(典型情况) —— 一个受管理的 ClientSession; 或者是一个具备事务功能的 Session (后者主要在Spring内部对TopLink的支持中被使用)。 还有一种情况,LocalSessionFactoryBean 可能会持有一个单线程的TopLink的 DatabaseSession,这是非常特殊的情况了。
TopLinkTemplate and TopLinkDaoSupport
每个基于TopLink的DAO将通过IoC被注入一个 SessionFactory, 你可以通过Setter方式注入,也可以用构造函数方式注入。这样的DAO可以直接操作原生的TopLink API,通过 SessionFactory 来获取一个 Session, 但是通常情况下,你更愿意使用Spring的 TopLinkTemplate:
<beans>
<bean id="myProductDao" class="product.ProductDaoImpl">
<property name="sessionFactory" ref="mySessionFactory"/>
</bean>
</beans>
public class TopLinkProductDao implements ProductDao {
private TopLinkTemplate tlTemplate;
public void setSessionFactory(SessionFactory sessionFactory) {
this.tlTemplate = new TopLinkTemplate(sessionFactory);
}
public Collection loadProductsByCategory(final String category) throws DataAccessException {
return (Collection) this.tlTemplate.execute(new TopLinkCallback() {
public Object doInTopLink(Session session) throws TopLinkException {
ReadAllQuery findOwnersQuery = new ReadAllQuery(Product.class);
findOwnersQuery.addArgument("Category");
ExpressionBuilder builder = this.findOwnersQuery.getExpressionBuilder();
findOwnersQuery.setSelectionCriteria(
builder.get("category").like(builder.getParameter("Category")));
Vector args = new Vector();
args.add(category);
List result = session.executeQuery(findOwnersQuery, args);
// do some further stuff with the result list
return result;
}
});
}
}
一个回调的实现能够有效地在任何TopLink数据访问中使用。TopLinkTemplate 会确保当前的 Session 对象的正确打开和关闭,并自动参与到事务管理中去。 Template实例不仅是线程安全的,同时它也是可重用的。因而他们可以作为外部对象的实例变量而被持有。对于那些简单的诸如 executeQuery、readAll、readById 和 merge 操作的调用,TopLinkTemplate提供可选择的快捷函数来替换这种回调的实现。 不仅如此,Spring还提供了一个简便的 TopLinkDaoSupport 基类,这个类提供了 setSessionFactory(..) 方法来接受一个 SessionFactory 对象,同时提供了 getSessionFactory() 和 getTopLinkTemplate() 方法给子类使用。综合了这些,对于那些典型的业务需求,就有了一个非常简单的DAO实现。
public class ProductDaoImpl extends TopLinkDaoSupport implements ProductDao {
public Collection loadProductsByCategory(String category) throws DataAccessException {
ReadAllQuery findOwnersQuery = new ReadAllQuery(Product.class);
findOwnersQuery.addArgument("Category");
ExpressionBuilder builder = this.findOwnersQuery.getExpressionBuilder();
findOwnersQuery.setSelectionCriteria(
builder.get("category").like(builder.getParameter("Category")));
return getTopLinkTemplate().executeQuery(findOwnersQuery, new Object[] {category});
}
}
边注:TopLink查询对象是线程安全的,并且能够在DAO层被缓存。在一开始被创建时以实例变量的方式被保持。
作为不使用Spring的 TopLinkTemplate 来实现DAO的替代解决方案, 你依然可以通过原生TopLink API对那些基于Spring的DAO进行编程,此时你必须明确地打开和关 闭一个 Session。正如在相应的Hibernate章节描述的 一样,这种做法的主要优点在于你的数据访问代码可以在整个过程中抛出checked exceptions。 TopLinkDaoSupport 为这种情况提供了多种函数支持,包括获取和释放 一个具备事务的 Session 并做相关的异常转化。
基于原生的TopLink API的DAO实现
我们可以直接操作TopLink API来实现DAO,直接使用一个注入的 Session 而无需对Spring产生的任何依赖。它通常基于一个由 LocalSessionFactoryBean 定义的 SessionFactory,并通过Spring的 TransactionAwareSessionAdapter 暴露成为一个 Session 类型的引用。
TopLink的 Session 接口中定义的 getActiveSession() 方法将返回当前具备事务管理功能的 Session 对象。如果当前没有处于活跃状态的事务, 这个函数将返回一个共享的TopLink的 ServerSession,也就是说, 这种情况应该只是一个直接使用的只读访问。另外还有一个 getActiveUnitOfWork() 方法, 返回TopLink的与当前事务绑定的 UnitOfWork (如果没有当前事务则返回 null)。
一个相应的DAO实现类看上去就像下面那样:
public class ProductDaoImpl implements ProductDao {
private Session session;
public void setSession(Session session) {
this.session = session;
}
public Collection loadProductsByCategory(String category) {
ReadAllQuery findOwnersQuery = new ReadAllQuery(Product.class);
findOwnersQuery.addArgument("Category");
ExpressionBuilder builder = this.findOwnersQuery.getExpressionBuilder();
findOwnersQuery.setSelectionCriteria(
builder.get("category").like(builder.getParameter("Category")));
Vector args = new Vector();
args.add(category);
return session.getActiveSession().executeQuery(findOwnersQuery, args);
}
}
上面我们所列出的DAO完全遵循IoC:它如同使用Spring的 TopLinkTemplate 进行编码那样,非常适合在application context中进行配置。Spring的 TransactionAwareSessionAdapter 将暴露一个 Session 类型的bean的引用,并传入到DAO中去:
<beans>
<bean id="mySessionAdapter"
class="org.springframework.orm.toplink.support.TransactionAwareSessionAdapter">
<property name="sessionFactory" ref="mySessionFactory"/>
</bean>
<bean id="myProductDao" class="product.ProductDaoImpl">
<property name="session" ref="mySessionAdapter"/>
</bean>
</beans>
这种DAO风格的主要好处在于它仅仅依赖于TopLink自身的API,而无需引入任何的Spring 的类。从无入侵性的角度来看,这一点非常吸引人。同时,对于TopLink的开发人员来说也更自然。
然而,这样的DAO访问方式会抛出 TopLinkException (这是一个无需声明或捕获的unchecked exception),这意味着,DAO的调用者只能以普通的 错误来处理这些异常,除非完全依赖TopLink自身的异常体系。因而,除非你将DAO的调用者绑定 到具体的实现策略上去,否则你将无法捕获特定的异常原因(诸如乐观锁异常)。这种折中平衡或许 可以被接受,如果你的应用完全基于TopLink或者无需进行特殊的异常处理。
这样的DAO风格有一个不利因素在于TopLink的标准的 getActiveSession() 函数仅仅在JTA事务中有效。而对于其他的事务管理策略尤其时本地的TopLink事务,它将 无法 工作。
幸运的是,Spring的 TransactionAwareSessionAdapter 为TopLink的 ServerSession 暴露了一个相应的代理类。 这个代理类能够在任何的事务策略之上支持TopLink的 Session.getActiveSession() 和 Session.getActiveUnitOfWork() 函数,返回当前收到Spring管理 (即便由 TopLinkTransactionManager 管理)的具备事务管理功能的 Session 实例。当然,这个函数的标准行为依然有效: 返回与当前的JTA事务绑定的 Session 对象。 (无论这个JTA事务是由Spring的 JtaTransactionManager、 EJB CMT或者普通的JTA所驱动的事务)。
总体来说,DAO可以基于TopLink的原生API实现,同时,它依旧需要能够参与到Spring的事务管理中。 这对于那些已经对TopLink非常熟悉的人来说很有吸引力,因为这种方式更加自然。不过,这种DAO将抛出 TopLinkException,因而,如果有必要的话需要明确地去做由 TopLinkException 到Spring的 DataAccessException 的转化。
事务管理
将事务管理纳入到Service操作的执行中,你可以使用Spring通用的声明式的事务管理功能,参加下面的例子:
<?xml version="1.0" encoding="UTF-8"?>
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
<bean id="myTxManager" class="org.springframework.orm.toplink.TopLinkTransactionManager">
<property name="sessionFactory" ref="mySessionFactory"/>
</bean>
<bean id="myProductService" class="product.ProductServiceImpl">
<property name="productDao" ref="myProductDao"/>
</bean>
<aop:config>
<aop:pointcut id="productServiceMethods" expression="execution(* product.ProductService.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="productServiceMethods"/>
</aop:config>
<tx:advice id="txAdvice" transaction-manager="myTxManager">
<tx:attributes>
<tx:method name="increasePrice*" propagation="REQUIRED"/>
<tx:method name="someOtherBusinessMethod" propagation="REQUIRES_NEW"/>
<tx:method name="*" propagation="SUPPORTS" read-only="true"/>
</tx:attributes>
</tx:advice>
</beans>
注意,TopLink要求你必须在一个活跃的 工作单元(UnitOfWork) 中修改一个持久化对象(你通常不能修改由普通的TopLink的 Session 查询返回的对象,因为这些对象通常是一些从二级缓存中读出的只读对象)。与Hibernate相比, 在TopLink中并没有一种类似脱离事务刷出(non-transactional flush)的概念。基于这 种原因,TopLink需要被建立在特定的环境中,尤其是它需要为JTA同步做明确的创建,由此来 自行检测一个JTA事务以及暴露一个相应的活跃的 Session 和 UnitOfWork。这一点对于本地事务不是必要的,由于它已经被 Spring的 TopLinkTransactionManager 处理,但是对于 需要参与到JTA事务中的情况,是必须的(无论是由Spring的 JtaTransactionManager、EJB CMT或者普通的JTA所驱动的事务)。
在你的基于TopLink的DAO代码中,你可以使用 Session.getActiveUnitOfWork() 方法来访问当前的 UnitOfWork 并通过它来执行写操作。这将只在一个活跃的事务中有效 (在一个收到Spring管理的事务或者JTA事务中)。对于特殊的需求,你同样可以获取单独的 UnitOfWork 实例,它将不参与到当前的事务中去,不过这种情况非常少。
TopLinkTransactionManager 能够将一个TopLink事务暴露给 访问相同的JDBC DataSource 的JDBC访问代码。 前提条件是,TopLink在底层是以JDBC方式工作的并且能够暴露底层的JDBC Connection。 这种情况下,用于暴露事务的 DataSource 必须被明确指定, 它是无法被自动检测到的。
分享到:
相关推荐
toplink 和spring 集成包
标题 "Spring2.5 Struts2.0 TopLink Ext2例子" 涉及到的是一个集成使用四个关键开源框架的示例项目,这些框架在Web应用开发中扮演着重要角色。下面将详细介绍这些框架以及它们如何协同工作。 1. **Spring**(2.5...
通过JPA,TopLink可以与其他遵循JPA的应用程序组件无缝集成,例如EJB和Spring框架。 6. **动态模型** TopLink的动态模型功能允许在运行时创建和修改对象模型,无需预定义实体类。这对于处理不稳定的数据库结构或...
Spring 2.0的'spring-jdo.jar', 'spring-jpa.jar', 'spring-hibernate3.jar', 'spring-toplink.jar' 和 'spring-ibatis.jar' 被合并到Spring 2.5大粒度的'spring-orm.jar'中。 Spring 2.5的 'spring-test.jar' 取代...
- **功能简介**:包含了 Web 应用开发时使用 Spring 框架时所需的核心类,包括自动载入 WebApplicationContext 特性的类、Struts 与 JSF 集成类、文件上传的支持类、Filter 类和大量工具辅助类。 - **应用场景**:...
2. Spring 2.0 的新特性 2.1. 简介 2.2. 控制反转(IoC)容器 2.2.1. 更简单的XML配置 2.2.2. 新的bean作用域 2.2.3. 可扩展的XML编写 2.3. 面向切面编程(AOP) 2.3.1. 更加简单的AOP XML配置 2.3.2. 对@AspectJ 切面的...
这个jar文件包含Spring对DAO特性集进行了扩展,使其支持 iBATIS、JDO、OJB、TopLink,因为Hibernate已经独立成包了,现在不包含在这个包里了。这个jar文件里大部分的类都要依赖 spring-dao.jar里的类,用这个包时你...
- Spring提供了一个高层抽象,允许开发者直接访问服务集成代码,如数据访问和Helper类,这增加了灵活性,但也可能限制了与具体服务提供商的解耦。 - EJB3.0则将服务集成封装在标准接口下,与应用服务器紧密结合。...
Spring 支持与各种技术的优雅集成,如Hibernate、JDO、TopLink、EJB、RMI、JNDI、JMS、Web服务和Struts等,为开发者提供了便利的接口和工具。 【模块化结构】 Spring 框架由多个模块组成,包括核心容器(Core ...
Spring可以与TopLink无缝集成,提供透明的数据访问。 8. **quartz**:Quartz是开源的作业调度库,用于计划和执行定时任务。Spring支持Quartz,可以方便地在Spring应用中配置和管理定时任务。 9. **jruby**:JRuby...
- 对 Spring DAO 特性集合进行了扩展,支持 iBATIS、JDO、TopLink 等 ORM 工具。 - 大部分的类都依赖于 `spring-dao.jar` 中的类。 9. **spring-remoting.jar** - 提供了对 EJB、JMS 以及远程调用(如 RMI、...
- **与其他框架的集成**:探讨了TopLink与Spring、EJB等其他流行框架的集成方式,以及这些集成带来的优势。 - **自定义扩展**:讲解了如何通过自定义扩展来增强TopLink的功能,例如添加自定义转换器、监听器等。 ...
在压缩包“Spring_JPA_TopLink”中,TopLink是Oracle提供的一个JPA实现,但在本案例中,它可能是作为例子或对比出现,因为通常提到的是Spring与Hibernate的结合,而非Spring与TopLink。文件列表可能包含配置文件(如...
2. Spring 2.0 的新特性 2.1. 简介 2.2. 控制反转(IoC)容器 2.2.1. 更简单的XML配置 2.2.2. 新的bean作用域 2.2.3. 可扩展的XML编写 2.3. 面向切面编程(AOP) 2.3.1. 更加简单的AOP XML配置 2.3.2. 对@...
SpringBoot集成了SpringDataJPA之后,就可以利用SpringBoot的自动配置能力,让开发者能够快速搭建和运行使用SpringDataJPA的项目。 在SpringBoot项目中整合SpringDataJPA,首先要导入必要的Maven依赖。在项目中,...
同时,OpenJPA可以与Spring框架和其他开源项目很好地集成,适合大型企业级应用。 **4. JPA批注** JPA批注是定义实体类和其属性与数据库表之间映射的关键部分。常用的批注包括: - `@Entity`:标记一个Java类作为...
除了以上这些核心jar包,Spring还有其他针对特定需求的模块,如Spring Security(安全)、Spring Batch(批处理)、Spring Integration(企业集成)和Spring Boot(快速启动微服务)等。这些jar包可以按需引入,以...
spring_jar包,适用于官网无法下载情况。 Spring的基本组成:最完善的轻量级核心框架。通用的事务管理抽象层。...集成了Toplink, Hibernate, JDO, and iBATIS SQL Maps。AOP功能。灵活的MVC Web应用框架。
**Spring框架的组成**包括但不限于:轻量级核心框架、通用的事务管理抽象层、JDBC抽象层以简化数据库操作、对Toplink、Hibernate、JDO、iBATIS SQL Maps等持久层框架的集成、AOP功能以及灵活的MVC Web应用框架。...