【Spring】Spring Framework Reference Documentation中文版16

20. Object Relational Mapping (ORM) Data Access

对象关系映射的数据访问

 

20.1 Introduction to ORM with Spring

介绍springORM

 

The Spring Framework supports integration with Hibernate, Java Persistence API (JPA) and Java Data Objects (JDO) for resource management, data access object (DAO) implementations, and transaction strategies. For example, for Hibernate there is first-class support with several convenient IoC features that address many typical Hibernate integration issues. You can configure all of the supported features for O/R (object relational) mapping tools through Dependency Injection. They can participate in Springs resource and transaction management, and they comply with Springs generic transaction and DAO exception hierarchies. The recommended integration style is to code DAOs against plain Hibernate, JPA, and JDO APIs. The older style of using Springs DAO templates is no longer recommended; however, coverage of this style can be found in the Section 39.1, Classic ORM usagein the appendices.

spring框架支持和Hibernate的集成、JPAJava数据Object对于资源的管理,数据访问object的实现和事务策略。例如,对于Hibernate首先支持一些方便的IOC特性对于许多类型的Hibernate集成问题。你可以配置所有对于OR的支持映射工具通过依赖注入。他们可以参与到spring的资源、事务管理和配合spring的通常事务、DAO异常的结构。推荐的集成风格对于DAO是普通的HibernateJPAJDOAPI。以前的方式是使用springDAO模板但是现在已经不推荐了,然而,这样的说明也可以在39.1节中找到,“经典的ORM的使用”,在附录中。

 

Spring adds significant enhancements to the ORM layer of your choice when you create data access applications. You can leverage as much of the integration support as you wish, and you should compare this integration effort with the cost and risk of building a similar infrastructure in-house. You can use much of the ORM support as you would a library, regardless of technology, because everything is designed as a set of reusable JavaBeans. ORM in a Spring IoC container facilitates configuration and deployment. Thus most examples in this section show configuration inside a Spring container.

spring添加了有效的加强层对于ORM层对于你的选择当你创建数据访问应用时。你可以利用大部分的集成根据你的需要,并且你应当比较这些集成对于消耗的影响和建造一个相似的内部结构的影响。你可以使用ORM支持作为一个库而忽略技术,因为所有的事情被设计作为一系列重用的JavaBeanORM是一个springIOC容器便于配置和开发。在这一节中的大部分例子展示了如果在spring的容器中配置。

 

Benefits of using the Spring Framework to create your ORM DAOs include:

使用spring框架来创建你的ORM DAO的好处包括:

 

    Easier testing. Springs IoC approach makes it easy to swap the implementations and configuration locations of Hibernate SessionFactory instances, JDBC DataSource instances, transaction managers, and mapped object implementations (if needed). This in turn makes it much easier to test each piece of persistence-related code in isolation.

易于测试。springioc方式使得可以简单的实现和配置HibernateSessionFactory的实例的位置,JDBC数据源实例,事务管理和映射object的实现(如果需要)。这是为了方便测试每一部分相关的持久化关系代码。

    Common data access exceptions. Spring can wrap exceptions from your ORM tool, converting them from proprietary (potentially checked) exceptions to a common runtime DataAccessException hierarchy. This feature allows you to handle most persistence exceptions, which are non-recoverable, only in the appropriate layers, without annoying boilerplate catches, throws, and exception declarations. You can still trap and handle exceptions as necessary. Remember that JDBC exceptions (including DB-specific dialects) are also converted to the same hierarchy, meaning that you can perform some operations with JDBC within a consistent programming model.

通用的数据访问异常。spring可以处理来自ORM工具的异常,将他们转换为普通的运行时DataAccessException结构。这个特性允许你来处理大部分持久化异常,有些是不可以恢复,在一些相关的层,不需要复杂的异常捕获、抛出和异常声明。你依然可以包装和处理异常如果是有必要的。记住JDBC异常(包括特定的数据库方言)依然可以被转换为相同的结构,意味着你可以执行一些操作通过一致的编程模型来操作JDBC

    General resource management. Spring application contexts can handle the location and configuration of Hibernate SessionFactory instances, JPA EntityManagerFactory instances, JDBC DataSource instances, and other related resources. This makes these values easy to manage and change. Spring offers efficient, easy, and safe handling of persistence resources. For example, related code that uses Hibernate generally needs to use the same Hibernate Session to ensure efficiency and proper transaction handling. Spring makes it easy to create and bind a Session to the current thread transparently, by exposing a current Session through the Hibernate SessionFactory. Thus Spring solves many chronic problems of typical Hibernate usage, for any local or JTA transaction environment.

通常的资源管理。spring应用上下文可以处理HibernateSessionFactory实例的位置和配置、JPAEntityManagerFactory实例、JDBC的数据源实例和其他相应资源。这使得这些值可以简单的管理和改变。spring提供了有效、简单和安全的处理持久化资源的方式。例如,相应的代码使用Hibernate需要系统的HibernateSession来保证有效和适当的事务处理。spring使得可以简单的创建和绑定一个Session显式对于当前的线程,暴露一个当前的Session通过HibernateSessionFactoryspring解决很多慢性的Hibernate使用中的问题,对于本地或JTA的事务环境。

    Integrated transaction management. You can wrap your ORM code with a declarative, aspect-oriented programming (AOP) style method interceptor either through the @Transactional annotation or by explicitly configuring the transaction AOP advice in an XML configuration file. In both cases, transaction semantics and exception handling (rollback, and so on) are handled for you. As discussed below, in Resource and transaction management, you can also swap various transaction managers, without affecting your ORM-related code. For example, you can swap between local transactions and JTA, with the same full services (such as declarative transactions) available in both scenarios. Additionally, JDBC-related code can fully integrate transactionally with the code you use to do ORM. This is useful for data access that is not suitable for ORM, such as batch processing and BLOB streaming, which still need to share common transactions with ORM operations.

集成事务管理。你可以包裹你的ORM代码通过声明、面向切面的方式方法拦截器通过@Transactional或在xml配置文件中明确配置AOPadvice。在两个例子中,事务语义和异常处理(回滚等等)可以被你来处理。就像下面套路的,在资源和事务管理中,你也可以交换不同的事务管理而不需要影响你的ORM相关代码。例如,你可以交换本地事务和JTA,使用相同的服务(例如声明式事务)在两种不同的情况。此外,JDBC相关的代码可以集成事务在你使用ORM的时候。这对于数据的访问是有用的但是不适合ORM,例如一个批处理和BLOB的流,依旧可以通过ORM操作在相同的事务中共享。

 

[Tip]

提示

 

For more comprehensive ORM support, including support for alternative database technologies such as MongoDB, you might want to check out the Spring Data suite of projects. If you are a JPA user, the Getting Started Accessing Data with JPA guide from https://spring.io provides a great introduction.

对于更复杂的ORM支持,包括不同数据库技术的支持如MongoDB,你可以查看springData相关工程。如果你是一个JPA的用户,可以查看来自https://spring.io提供的指南关于开始数据访问通过JPA指南。

 

20.2 General ORM integration considerations

通常的ORM集成考虑

 

This section highlights considerations that apply to all ORM technologies. The Section 20.3, Hibernatesection provides more details and also show these features and configurations in a concrete context.

这个章节重点考虑的有关ORM技术的应用。20.3节“Hibernate”章节提供了更多的细节并且展示了这些特性和配置在一个混合的上下文中。

 

The major goal of Springs ORM integration is clear application layering, with any data access and transaction technology, and for loose coupling of application objects. No more business service dependencies on the data access or transaction strategy, no more hard-coded resource lookups, no more hard-to-replace singletons, no more custom service registries. One simple and consistent approach to wiring up application objects, keeping them as reusable and free from container dependencies as possible. All the individual data access features are usable on their own but integrate nicely with Springs application context concept, providing XML-based configuration and cross-referencing of plain JavaBean instances that need not be Spring-aware. In a typical Spring application, many important objects are JavaBeans: data access templates, data access objects, transaction managers, business services that use the data access objects and transaction managers, web view resolvers, web controllers that use the business services,and so on.

springORM集成的主要目标是干净的应用层,通过数据访问和事务技术,并且适用于松耦合应用的object。不需要业务服务依赖对于数据访问或事务策略,不需要硬编码资源查找,不需要硬替换单例,不需要自定义服务注册。一个简单的一致的方式来处理应用object,保证他们可以重用并且可以不依赖容器的依赖。所有独立的数据访问特性可以重用他们本身但是很好的集成spring的应用上下文概念、提供基于xml的配置和跨引用的普通JavaBean实例不需要Spring-aware。在一个普通的spring的应用中,许多重要的objectJavaBean:数据访问模板、数据访问object、事务管理、业务服务并使用数据访问objectweb页面解析、web控制需要使用业务服务等。

 

20.2.1 Resource and transaction management

资源和事务管理

 

Typical business applications are cluttered with repetitive resource management code. Many projects try to invent their own solutions, sometimes sacrificing proper handling of failures for programming convenience. Spring advocates simple solutions for proper resource handling, namely IoC through templating in the case of JDBC and applying AOP interceptors for the ORM technologies.

通常业务应用混杂着重复的资源代码。许多项目试图介绍他们的解决方案,有时牺牲适当的错误处理为了编程的方便。spring拥护简单的解决访问对于适当的资源处理、命名IOC通过模板由于JDBC并且应用AOP拦截器对于ORM技术。

 

The infrastructure provides proper resource handling and appropriate conversion of specific API exceptions to an unchecked infrastructure exception hierarchy. Spring introduces a DAO exception hierarchy, applicable to any data access strategy. For direct JDBC, the JdbcTemplate class mentioned in a previous section provides connection handling and proper conversion of SQLException to the DataAccessException hierarchy, including translation of database-specific SQL error codes to meaningful exception classes. For ORM technologies, see the next section for how to get the same exception translation benefits.

基础设施提供了适当的资源处理和对于特定API异常的适当转换对于一个非检查的基础设施异常结构。spring引入了一个DAO异常结构,应用任何数据访问的策略。对于直接的JDBC,之前章节中提到的JdbcTemplate类提供了连接处理和对于SQLException的适当转换到DataAccessException的结构,包括特定数据库SQL错误代码的翻译对于有意义的异常类。对于ORM技术,可以看下一节对于获得相同异常翻译的好处。

 

When it comes to transaction management, the JdbcTemplate class hooks in to the Spring transaction support and supports both JTA and JDBC transactions, through respective Spring transaction managers. For the supported ORM technologies Spring offers Hibernate, JPA and JDO support through the Hibernate, JPA, and JDO transaction managers as well as JTA support. For details on transaction support, see the Chapter 17, Transaction Management chapter.

当处理事务管理,JdbcTemplate类在spring中事务支持钩子并且支持JTAJDBC事务,通过相应的spring的事务管理。对于支持ORM技术spring提供了HibernateJPAJDO支持通过HibernateJPAJDO事务管理就像JTA支持。事务支持的详细细节,见17章,事务管理章节。

 

20.2.2 Exception translation

异常翻译

 

When you use Hibernate, JPA, or JDO in a DAO, you must decide how to handle the persistence technologys native exception classes. The DAO throws a subclass of a HibernateException, PersistenceException or JDOException depending on the technology. These exceptions are all run-time exceptions and do not have to be declared or caught. You may also have to deal with IllegalArgumentException and IllegalStateException. This means that callers can only treat exceptions as generally fatal, unless they want to depend on the persistence technologys own exception structure. Catching specific causes such as an optimistic locking failure is not possible without tying the caller to the implementation strategy. This trade off might be acceptable to applications that are strongly ORM-based and/or do not need any special exception treatment. However, Spring enables exception translation to be applied transparently through the @Repository annotation:

当你使用HibernateJPAJDODAO中时,你必须决定如何处理持久化技术的本地异常类。DAO依赖这些技术,抛出HibernateExceptionPersistenceExceptionJDOException的子类。这些异常都是运行时异常并且不需要声明和捕获。你也可以处理IllegalArgumentExceptionIllegalStateException。这意味着调用者可以处理异常作为普通的错误,除非他们希望依赖持久化技术自己的异常结构。处理特定的引用例如乐观锁失败是不需要调用实现策略的。这些权衡可能适合于应用依赖于基于ORM并且不需要任何特定的异常处理。然而,spring允许异常翻译来应用通过@Repository注解:

 

@Repository

public class ProductDaoImpl implements ProductDao {

 

    // class body here...

 

}

 

<beans>

 

    <!-- Exception translation bean post processor -->

    <bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>

 

    <bean id="myProductDao" class="product.ProductDaoImpl"/>

 

</beans>

 

The postprocessor automatically looks for all exception translators (implementations of the PersistenceExceptionTranslator interface) and advises all beans marked with the @Repository annotation so that the discovered translators can intercept and apply the appropriate translation on the thrown exceptions.

处理器自动查找所有的异常翻译(实现了PersistenceExceptionTranslator接口)并且通知所有的bean使用@Repository注解因此发现翻译器可以拦截并应用适当的翻译通过抛出异常。

 

In summary: you can implement DAOs based on the plain persistence technologys API and annotations, while still benefiting from Spring-managed transactions, dependency injection, and transparent exception conversion (if desired) to Springs custom exception hierarchies.

总结一下:你可以实现DAO基于普通的持久化API和注解,依然可以从spring管理的事务、依赖注入和显示异常转换中获益(如果值得)对于spring的自定义异常结构。

 

20.3 Hibernate

 

We will start with a coverage of Hibernate 5 in a Spring environment, using it to demonstrate the approach that Spring takes towards integrating O/R mappers. This section will cover many issues in detail and show different variations of DAO implementations and transaction demarcation. Most of these patterns can be directly translated to all other supported ORM tools. The following sections in this chapter will then cover the other ORM technologies, showing briefer examples there.

我们将会开始覆盖Hibernate5spring的环境中,使用描述的方式使得spring来基层OR映射。这一节将包括许多问题的细节并展示不同的DAO实现和翻译描述。这些方式的大部分可以直接通过所有其他的ORM工具来支持。这节中下面的内容将包括ORM技术,展示简单的例子。

 

[Note]

注意

 

As of Spring 4.0, Spring requires Hibernate 3.6 or later. Note that the Hibernate team stopped supporting Hibernate 3 years ago and even phased out support for Hibernate 4.x in late 2015. We therefore recommend Hibernate 5.1 and higher from a 2016+ perspective.

由于spring4.0spring要求Hibernate最低版本是3.6及以上。注意Hibernate小组停止支持Hibernate3在很多年之前并且Hibernate4.x最多支持到2015年。我们建议Hibernate5.1或更高的2016之后的版本。

 

20.3.1 SessionFactory setup in a Spring container

spring容器中设置SessionFactory

 

To avoid tying application objects to hard-coded resource lookups, you can define resources such as a JDBC DataSource or a Hibernate SessionFactory as beans in the Spring container. Application objects that need to access resources receive references to such predefined instances through bean references, as illustrated in the DAO definition in the next section.

为了避免硬编码资源查找的方式,你可以定义资源类似于一个JDBC数据源或一个HibernateSessionFactory作为一个beanspring的容器中。应用object需要访问资源接收应用对于这样提前定义的实例通过bean的引用,作为DAO的定义在下一节中描述。

 

The following excerpt from an XML application context definition shows how to set up a JDBC DataSource and a Hibernate SessionFactory on top of it:

下面的内容来自xml的应用上下文展示了如何设置一个JDBC数据源和HibernateSessionFactory

 

<beans>

 

    <bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">

        <property name="driverClassName" value="org.hsqldb.jdbcDriver"/>

        <property name="url" value="jdbc:hsqldb:hsql://localhost:9001"/>

        <property name="username" value="sa"/>

        <property name="password" value=""/>

    </bean>

 

    <bean id="mySessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">

        <property name="dataSource" ref="myDataSource"/>

        <property name="mappingResources">

            <list>

                <value>product.hbm.xml</value>

            </list>

        </property>

        <property name="hibernateProperties">

            <value>

                hibernate.dialect=org.hibernate.dialect.HSQLDialect

            </value>

        </property>

    </bean>

 

</beans>

 

Switching from a local Jakarta Commons DBCP BasicDataSource to a JNDI-located DataSource (usually managed by an application server) is just a matter of configuration:

将一个本地的Jakarta Commons DBCP BasicDataSource切换为基于JNDI的数据源(通常通过一个应用服务器来管理)只需要一个配置:

 

<beans>

    <jee:jndi-lookup id="myDataSource" jndi-name="java:comp/env/jdbc/myds"/>

</beans>

 

You can also access a JNDI-located SessionFactory, using Springs JndiObjectFactoryBean / <jee:jndi-lookup> to retrieve and expose it. However, that is typically not common outside of an EJB context.

你也可以访问基于JNDISessionFactory,使用springJndiObjectFactoryBean / <jee:jndi-lookup>来接收并展示他。然而,通常不会在EJB上下文的外面。

 

20.3.2 Implementing DAOs based on plain Hibernate API

基于普通的Hibernate API实现DAO

 

Hibernate has a feature called contextual sessions, wherein Hibernate itself manages one current Session per transaction. This is roughly equivalent to Springs synchronization of one Hibernate Session per transaction. A corresponding DAO implementation resembles the following example, based on the plain Hibernate API:

Hibernate有一个特性名字为上下文会话,在Hibernate中管理每个事务中的当前会话。这和spring对于一个Hibernate会话的每个事务进行同步差不多。一个相应的DAO实现类似于下面的例子,基于普通的HibernateAPI

 

public class ProductDaoImpl implements ProductDao {

 

    private SessionFactory sessionFactory;

 

    public void setSessionFactory(SessionFactory sessionFactory) {

        this.sessionFactory = sessionFactory;

    }

 

    public Collection loadProductsByCategory(String category) {

        return this.sessionFactory.getCurrentSession()

                .createQuery("from test.Product product where product.category=?")

                .setParameter(0, category)

                .list();

    }

}

 

This style is similar to that of the Hibernate reference documentation and examples, except for holding the SessionFactory in an instance variable. We strongly recommend such an instance-based setup over the old-school static HibernateUtil class from Hibernates CaveatEmptor sample application. (In general, do not keep any resources in static variables unless absolutely necessary.)

这种风格和Hibernate应用文档和例子相似,处理在一个实例变量中持有一个SessionFactory。我们强烈推荐这样基于实例的设置而不是老式的静态HibernateUtil类来自HibernateCaveatEmptor案例中。(通常,不需要持有任何资源在静态变量除非是必要的。)

 

The above DAO follows the dependency injection pattern: it fits nicely into a Spring IoC container, just as it would if coded against Springs HibernateTemplate. Of course, such a DAO can also be set up in plain Java (for example, in unit tests). Simply instantiate it and call setSessionFactory(..) with the desired factory reference. As a Spring bean definition, the DAO would resemble the following:

上面的DAO遵循依赖注入的模式:他很好的适合了springIOC容器,就像他可以适合springHibernateTemplate。当然,这样的DAO也可以被设置通过普通的Java方式(例如在单元测试中)。简单的实例化他并调用setSessionFactory传递预期的工程引用。作为一个springbean定义,DAO可以声明如下:

 

<beans>

 

    <bean id="myProductDao" class="product.ProductDaoImpl">

        <property name="sessionFactory" ref="mySessionFactory"/>

    </bean>

 

</beans>

 

The main advantage of this DAO style is that it depends on Hibernate API only; no import of any Spring class is required. This is of course appealing from a non-invasiveness perspective, and will no doubt feel more natural to Hibernate developers.

这种DAO风格主要的优点是他只依赖HibernateAPI,不需要导入spring的类。这样当然没有任何侵入性,并且会觉得很自然对于Hibernate的开发者。

 

However, the DAO throws plain HibernateException (which is unchecked, so does not have to be declared or caught), which means that callers can only treat exceptions as generally fatal - unless they want to depend on Hibernates own exception hierarchy. Catching specific causes such as an optimistic locking failure is not possible without tying the caller to the implementation strategy. This trade off might be acceptable to applications that are strongly Hibernate-based and/or do not need any special exception treatment.

然而,DAO抛出普通的HibernateException(是非检查的,引起不需要声明或捕获),意味着调用者只需要处理通常的错误————除非他们希望依赖Hibernate自身的异常结构。捕获特定的原因例如乐观锁失败是不可能的除非调用实现策略。这种方式适合应用是基于Hibernate不需要特定的异常处理。

 

Fortunately, Springs LocalSessionFactoryBean supports Hibernates SessionFactory.getCurrentSession() method for any Spring transaction strategy, returning the current Spring-managed transactional Session even with HibernateTransactionManager. Of course, the standard behavior of that method remains the return of the current Session associated with the ongoing JTA transaction, if any. This behavior applies regardless of whether you are using Springs JtaTransactionManager, EJB container managed transactions (CMTs), or JTA.

幸运的是,springLocalSessionFactoryBean支持HibernateSessionFactory.getCurrentSession()方法对于任何spring的事务策略,返回当前spring管理的事务会话甚至通过HibernateTransactionManager。当然,这个方法标准的行为保留返回当前的会话连接不间断的JTA事务,如何可以的话。这种行为不管你使用springJtaTransactionManagerEJB容器管理事务或JTA

 

In summary: you can implement DAOs based on the plain Hibernate API, while still being able to participate in Spring-managed transactions.

总结:你可以基于普通的HibernateAPI引入DAO,依然可以参与spring管理的事务。

 

20.3.3 Declarative transaction demarcation

声明事务的划分

 

We recommend that you use Springs declarative transaction support, which enables you to replace explicit transaction demarcation API calls in your Java code with an AOP transaction interceptor. This transaction interceptor can be configured in a Spring container using either Java annotations or XML.This declarative transaction capability allows you to keep business services free of repetitive transaction demarcation code and to focus on adding business logic, which is the real value of your application.

我们建议你使用spring的声明式事务支持,允许你替代显式的事务划分API调用在你的Java代码中通过AOP的事务拦截器。这个是我拦截器可以被配置在spring的容器中使用Java注解或XML。这个声明事务允许你保持业务的自由有关声明式事务隔离代码并且不强制添加业务逻辑,对于你的应用。

 

[Note]

注意

 

Prior to continuing, you are strongly encouraged to read Section 17.5, Declarative transaction managementif you have not done so.

之前的继续,我们强烈建议你阅读17.5节,“声明式事务管理”如果你没有读过的话。

 

Furthermore, transaction semantics like propagation behavior and isolation level can be changed in a configuration file and do not affect the business service implementations.

此外,事务语义就像传播行为和隔离级别可以在配置文件中改变并且不会影响到业务服务的实现:

 

The following example shows how you can configure an AOP transaction interceptor, using XML, for a simple service class:

下面的例子展示如何配置一个AOP事务拦截器,使用xml,对于一个简单的服务类:

 

<?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.xsd

        http://www.springframework.org/schema/tx

        http://www.springframework.org/schema/tx/spring-tx.xsd

        http://www.springframework.org/schema/aop

        http://www.springframework.org/schema/aop/spring-aop.xsd">

 

    <!-- SessionFactory, DataSource, etc. omitted -->

 

    <bean id="transactionManager"

            class="org.springframework.orm.hibernate5.HibernateTransactionManager">

        <property name="sessionFactory" ref="sessionFactory"/>

    </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>

 

    <bean id="myProductService" class="product.SimpleProductService">

        <property name="productDao" ref="myProductDao"/>

    </bean>

 

</beans>

 

This is the service class that is advised:

这个服务类是这样的:

 

public class ProductServiceImpl implements ProductService {

 

    private ProductDao productDao;

 

    public void setProductDao(ProductDao productDao) {

        this.productDao = productDao;

    }

 

    // notice the absence of transaction demarcation code in this method

    // Spring's declarative transaction infrastructure will be demarcating

    // transactions on your behalf

    public void increasePriceOfAllProductsInCategory(final String category) {

        List productsToChange = this.productDao.loadProductsByCategory(category);

        // ...

    }

}

 

We also show an attribute-support based configuration, in the following example. You annotate the service layer with @Transactional annotations and instruct the Spring container to find these annotations and provide transactional semantics for these annotated methods.

我们也展示了支持属性的配置,在下面的例子中。你声明一个服务层通过@Transactional注解并指定spring容器来查找这些注解并提供事务语义对于这些声明方法。

 

public class ProductServiceImpl implements ProductService {

 

    private ProductDao productDao;

 

    public void setProductDao(ProductDao productDao) {

        this.productDao = productDao;

    }

 

    @Transactional

    public void increasePriceOfAllProductsInCategory(final String category) {

        List productsToChange = this.productDao.loadProductsByCategory(category);

        // ...

    }

 

    @Transactional(readOnly = true)

    public List<Product> findAllProducts() {

        return this.productDao.findAllProducts();

    }

 

}

 

As you can see from the following configuration example, the configuration is much simplified, compared to the XML example above, while still providing the same functionality driven by the annotations in the service layer code. All you need to provide is the TransactionManager implementation and a "<tx:annotation-driven/>" entry.

就像你可以看到的下面的配置案例,配置是很简单的,对于上面的xml,但是依然提供了相同的功能对于服务层代码中的注解。所有你需要提供的是一个TransactionManager和一个"<tx:annotation-driven/>"配置。

 

<?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.xsd

        http://www.springframework.org/schema/tx

        http://www.springframework.org/schema/tx/spring-tx.xsd

        http://www.springframework.org/schema/aop

        http://www.springframework.org/schema/aop/spring-aop.xsd">

 

    <!-- SessionFactory, DataSource, etc. omitted -->

 

    <bean id="transactionManager"

            class="org.springframework.orm.hibernate5.HibernateTransactionManager">

        <property name="sessionFactory" ref="sessionFactory"/>

    </bean>

 

    <tx:annotation-driven/>

 

    <bean id="myProductService" class="product.SimpleProductService">

        <property name="productDao" ref="myProductDao"/>

    </bean>

 

</beans>

 

20.3.4 Programmatic transaction demarcation

编程事务划分

 

You can demarcate transactions in a higher level of the application, on top of such lower-level data access services spanning any number of operations. Nor do restrictions exist on the implementation of the surrounding business service; it just needs a Spring PlatformTransactionManager. Again, the latter can come from anywhere, but preferably as a bean reference through a setTransactionManager(..) method, just as the productDAO should be set by a setProductDao(..) method. The following snippets show a transaction manager and a business service definition in a Spring application context, and an example for a business method implementation:

你可以分离事务以一种高级别对于应用来说,这样低级别的数据访问服务跨越任意的操作。不限制实现业务服务:只需要一个springPlatformTransactionManager。再次,后序可以来自任何但是最好作为一个bean的引用通过setTransactionManager方法,就像productDAO应该被设置通过setProductDao方法一样。下面的片段展示了一个事务管理和一个业务服务定义在spring的应用上下文并且是一个对于业务方法实现的例子:

 

<beans>

 

    <bean id="myTxManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager">

        <property name="sessionFactory" ref="mySessionFactory"/>

    </bean>

 

    <bean id="myProductService" class="product.ProductServiceImpl">

        <property name="transactionManager" ref="myTxManager"/>

        <property name="productDao" ref="myProductDao"/>

    </bean>

 

</beans>

 

public class ProductServiceImpl implements ProductService {

 

    private TransactionTemplate transactionTemplate;

    private ProductDao productDao;

 

    public void setTransactionManager(PlatformTransactionManager transactionManager) {

        this.transactionTemplate = new TransactionTemplate(transactionManager);

    }

 

    public void setProductDao(ProductDao productDao) {

        this.productDao = productDao;

    }

 

    public void increasePriceOfAllProductsInCategory(final String category) {

        this.transactionTemplate.execute(new TransactionCallbackWithoutResult() {

            public void doInTransactionWithoutResult(TransactionStatus status) {

                List productsToChange = this.productDao.loadProductsByCategory(category);

                // do the price increase...

            }

        });

    }

}

 

Springs TransactionInterceptor allows any checked application exception to be thrown with the callback code, while TransactionTemplate is restricted to unchecked exceptions within the callback. TransactionTemplate triggers a rollback in case of an unchecked application exception, or if the transaction is marked rollback-only by the application (via TransactionStatus). TransactionInterceptor behaves the same way by default but allows configurable rollback policies per method.

springTransactionInterceptor允许任何检查应用异常被抛出通过回调代码,当TransactionTemplate被限制为非限制异常对于回调来说。TransactionTemplate引发回滚在一个非检查的应用异常中或如果事务被标记为只回滚通过应用(通过TransactionStatus)。TransactionInterceptor会有相同的行为在默认的情况下但是允许对于每个方法配置回滚策略。

 

20.3.5 Transaction management strategies

事务管理策略

 

Both TransactionTemplate and TransactionInterceptor delegate the actual transaction handling to a PlatformTransactionManager instance, which can be a HibernateTransactionManager (for a single Hibernate SessionFactory, using a ThreadLocal Session under the hood) or a JtaTransactionManager (delegating to the JTA subsystem of the container) for Hibernate applications. You can even use a custom PlatformTransactionManager implementation. Switching from native Hibernate transaction management to JTA, such as when facing distributed transaction requirements for certain deployments of your application, is just a matter of configuration. Simply replace the Hibernate transaction manager with Springs JTA transaction implementation. Both transaction demarcation and data access code will work without changes, because they just use the generic transaction management APIs.

TransactionTemplateTransactionInterceptor委托实际的事务处理对于PlatformTransactionManager实例,可以作为一个HibernateTransactionManager(对于一个简单的HibernateSessionFactory使用一个线程本地的会话在引擎后面)或一个JtaTransactionManager(委托给容器的JTA子系统)对于Hibernate应用。你甚至可以使用一个自定义的PlatformTransactionManager实现。切换本地Hibernate事务管理到JTA,就像处理分布式事务需求对于特定的应用开发,就是一个配置问题。简单的替换Hibernate事务管理通过JTA事务实现。事务隔离和数据访问代码将不需要任何改变,因为只是使用了通常的事务管理API

 

For distributed transactions across multiple Hibernate session factories, simply combine JtaTransactionManager as a transaction strategy with multiple LocalSessionFactoryBean definitions. Each DAO then gets one specific SessionFactory reference passed into its corresponding bean property. If all underlying JDBC data sources are transactional container ones, a business service can demarcate transactions across any number of DAOs and any number of session factories without special regard, as long as it is using JtaTransactionManager as the strategy.

对于分布式事务跨越多个Hibernate的会话工厂,简单的合并JtaTransactionManager作为一个事务策略对于多个LocalSessionFactoryBean定义。每个DAO获得一个特定的SessionFactory引用传递给相应的bean属性。如果每个JDBC数据资源下是事务容器,一个业务服务可以区分事务在任意数量的DAO中并且会话工程的数量不需要有特定的考虑,可以使用JtaTransactionManager作为策略。

 

<beans>

 

    <jee:jndi-lookup id="dataSource1" jndi-name="java:comp/env/jdbc/myds1"/>

 

    <jee:jndi-lookup id="dataSource2" jndi-name="java:comp/env/jdbc/myds2"/>

 

    <bean id="mySessionFactory1"

            class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">

        <property name="dataSource" ref="myDataSource1"/>

        <property name="mappingResources">

            <list>

                <value>product.hbm.xml</value>

            </list>

        </property>

        <property name="hibernateProperties">

            <value>

                hibernate.dialect=org.hibernate.dialect.MySQLDialect

                hibernate.show_sql=true

            </value>

        </property>

    </bean>

 

    <bean id="mySessionFactory2"

            class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">

        <property name="dataSource" ref="myDataSource2"/>

        <property name="mappingResources">

            <list>

                <value>inventory.hbm.xml</value>

            </list>

        </property>

        <property name="hibernateProperties">

            <value>

                hibernate.dialect=org.hibernate.dialect.OracleDialect

            </value>

        </property>

    </bean>

 

    <bean id="myTxManager" class="org.springframework.transaction.jta.JtaTransactionManager"/>

 

    <bean id="myProductDao" class="product.ProductDaoImpl">

        <property name="sessionFactory" ref="mySessionFactory1"/>

    </bean>

 

    <bean id="myInventoryDao" class="product.InventoryDaoImpl">

        <property name="sessionFactory" ref="mySessionFactory2"/>

    </bean>

 

    <bean id="myProductService" class="product.ProductServiceImpl">

        <property name="productDao" ref="myProductDao"/>

        <property name="inventoryDao" ref="myInventoryDao"/>

    </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>

 

Both HibernateTransactionManager and JtaTransactionManager allow for proper JVM-level cache handling with Hibernate, without container-specific transaction manager lookup or a JCA connector (if you are not using EJB to initiate transactions).

HibernateTransactionManagerJtaTransactionManager运行适当的JVM级别的缓存处理通过Hibernate,不需要特定容器的事务管理查找或JCA连接器(如果你不使用EJB来开始事务)。

 

HibernateTransactionManager can export the Hibernate JDBC Connection to plain JDBC access code, for a specific DataSource. This capability allows for high-level transaction demarcation with mixed Hibernate and JDBC data access completely without JTA, if you are accessing only one database. HibernateTransactionManager automatically exposes the Hibernate transaction as a JDBC transaction if you have set up the passed-in SessionFactory with a DataSource through the dataSource property of the LocalSessionFactoryBean class. Alternatively, you can specify explicitly the DataSource for which the transactions are supposed to be exposed through the dataSource property of the HibernateTransactionManager class.

HibernateTransactionManager可以导出普通的JDBC跨代码,对于一个特定的数据源。这允许一个高级别的事务隔离通过混合的HibernateJDBC数据访问完全不依赖JTA,如果你只访问一个数据库。HibernateTransactionManager自动暴露Hibernate事务作为一个JDBC事务如果你设置传递一个数据源给SessionFactory通过LocalSessionFactoryBean类的属性。作为替代,你可以明确指定数据源对于事务被支持用于暴露通过HibernateTransactionManager类的dataSource属性。

 

20.3.6 Comparing container-managed and locally defined resources

比较容器管理和本地定义资源

 

You can switch between a container-managed JNDI SessionFactory and a locally defined one, without having to change a single line of application code. Whether to keep resource definitions in the container or locally within the application is mainly a matter of the transaction strategy that you use. Compared to a Spring-defined local SessionFactory, a manually registered JNDI SessionFactory does not provide any benefits. Deploying a SessionFactory through Hibernates JCA connector provides the added value of participating in the Java EE servers management infrastructure, but does not add actual value beyond that.

你可以切换容器管理JNDISessionFactory和本地定义不需要改变一行应用代码。保持资源定义在容器中或本地在应用中主要问题是你使用的事务策略。对比spring定义的本地SessionFactory,一个手动注册JNDISessionFactory没有提供任何益处。通过HibernateJCA连接部署一个SessionFactory提供添加值在JavaEE服务器的管理中,但是不能添加实际值。

 

Springs transaction support is not bound to a container. Configured with any strategy other than JTA, transaction support also works in a stand-alone or test environment. Especially in the typical case of single-database transactions, Springs single-resource local transaction support is a lightweight and powerful alternative to JTA. When you use local EJB stateless session beans to drive transactions, you depend both on an EJB container and JTA, even if you access only a single database, and only use stateless session beans to provide declarative transactions through container-managed transactions. Also, direct use of JTA programmatically requires a Java EE environment as well. JTA does not involve only container dependencies in terms of JTA itself and of JNDI DataSource instances. For non-Spring, JTA-driven Hibernate transactions, you have to use the Hibernate JCA connector, or extra Hibernate transaction code with the TransactionManagerLookup configured for proper JVM-level caching.

spring的事务支持没有绑定到容器。和JTA不同可以配置任何策略,也可以独立使用或在测试环境中工作。尤其是在典型的单数据事务中,spring的单资源本地事务支持是轻量级的并且是功能强大的对于JTA来说。当你使用本地的EJB无状态会话bean来驱动事务,你依赖EJB容器和JTA即使你只是访问当个数据库并且使用了无状态会话bean来提供声明式事务通过容器管理的事务。并且直接编程使用JTA也需要一个JavaEE环境。JTA不会只依赖容器和JNDI的数据源实例。对于非spring,基于JTAHibernate事务,你需要使用HibernateJCA连接器或额外的Hibernate事务代码通过TransactionManagerLookup的配置对于JVM级别的缓存。

 

Spring-driven transactions can work as well with a locally defined Hibernate SessionFactory as they do with a local JDBC DataSource if they are accessing a single database. Thus you only have to use Springs JTA transaction strategy when you have distributed transaction requirements. A JCA connector requires container-specific deployment steps, and obviously JCA support in the first place. This configuration requires more work than deploying a simple web application with local resource definitions and Spring-driven transactions. Also, you often need the Enterprise Edition of your container if you are using, for example, WebLogic Express, which does not provide JCA. A Spring application with local resources and transactions spanning one single database works in any Java EE web container (without JTA, JCA, or EJB) such as Tomcat, Resin, or even plain Jetty. Additionally, you can easily reuse such a middle tier in desktop applications or test suites.

基于spring的事务可以工作和本地定义的HibernateSeesionFactory使用本地的JDBC数据源如果他们创建单个数据库。你只需要使用springJTA事务策略当你有分布式事务的需求时。一个JCA容器需要特定的容器部署和明确的JCA支持作为第一位。这种配置要求需要步数一个简单的web应用使用本地资源定义和基于spring的事务。并且你需要一个企业级版本的容器如果你使用的话,例如,WebLogic Express,不需要提供JCA。一个spring应用使用本地资源和事务跨越单个数据库工作在JavaEEweb容器中(不需要JTAJCAEJB)例如TomcatResin或甚至是Jetty。此外,你可以简单的重用这样的中间件来连接桌面应用或测试套件。

 

All things considered, if you do not use EJBs, stick with local SessionFactory setup and Springs HibernateTransactionManager or JtaTransactionManager. You get all of the benefits, including proper transactional JVM-level caching and distributed transactions, without the inconvenience of container deployment. JNDI registration of a Hibernate SessionFactory through the JCA connector only adds value when used in conjunction with EJBs.

所有的事情都被考虑了,如果你不使用EJB,将本地SessionFactory设置和springHibernateTransactionManagerJtaTransactionManager连接在一起。你获得了很多好处,包括适当的事务JVM级别缓存和分布式事务,不需要依赖容器的部署。HibernateSessionFactoryJNDI注册通过JCA容器只需要添加值通过EJB使用。

 

20.3.7 Spurious application server warnings with Hibernate

使用Hibernate伪造应用服务器警告

 

In some JTA environments with very strict XADataSource implementations — currently only some WebLogic Server and WebSphere versions — when Hibernate is configured without regard to the JTA PlatformTransactionManager object for that environment, it is possible for spurious warning or exceptions to show up in the application server log. These warnings or exceptions indicate that the connection being accessed is no longer valid, or JDBC access is no longer valid, possibly because the transaction is no longer active. As an example, here is an actual exception from WebLogic:

在一些JTA环境中有非常严格的XADataSource实现————当时只有一些WebLogic服务器和WebSphere的部分版本————当Hibernate被配置不需要JTAPlatformTransactionManager对于这些环境,他可以伪造警告或异常出现在应用服务器的日志中。这些警告或异常的连接访问将不在有效、或JDBC访问将不在有效,有时因为事务不会被激活。例如,有一个实际的异常来自WebLogic

 

java.sql.SQLException: The transaction is no longer active - status: 'Committed'. No further JDBC access is allowed within this transaction.

 

You resolve this warning by simply making Hibernate aware of the JTA PlatformTransactionManager instance, to which it will synchronize (along with Spring). You have two options for doing this:

你解决异常通常是简单的标记的Hibernate了解PlatformTransactionManager实例,将会同步(和spring)。你有两个选项对于这件事:

 

    If in your application context you are already directly obtaining the JTA PlatformTransactionManager object (presumably from JNDI through JndiObjectFactoryBean or <jee:jndi-lookup>) and feeding it, for example, to Springs JtaTransactionManager, then the easiest way is to specify a reference to the bean defining this JTA PlatformTransactionManager instance as the value of the jtaTransactionManager property for LocalSessionFactoryBean. Spring then makes the object available to Hibernate.

如果在你的应用上下文你已经直接获得了JTAPlatformTransactionManagerobject(推测来自JNDI通过JndiObjectFactoryBean<jee:jndi-lookup>)和处理他们,例如,对于springJtaTransactionManager,最简单的方法就是定义一个bean的引用定义在JTAPlatformTransactionManager实例作为LocalSessionFactoryBeanjtaTransactionManager属性值。spring 使得object对于Hibernate可用。

    More likely you do not already have the JTA PlatformTransactionManager instance, because Springs JtaTransactionManager can find it itself. Thus you need to configure Hibernate to look up JTA PlatformTransactionManager directly. You do this by configuring an application server- specific TransactionManagerLookup class in the Hibernate configuration, as described in the Hibernate manual.

就像你没有JTAPlatformTransactionManager实例,因为springJtaTransactionManager可以发现本身。你需要配置Hibernate来直接查找JTAPlatformTransactionManager。你通过配置应用服务器指定TransactionManagerLookupHibernate的配置中,这种做法描述在Hibernate的手册中。

 

The remainder of this section describes the sequence of events that occur with and without Hibernates awareness of the JTA PlatformTransactionManager.

这节剩余的内容描述事件发生的顺序不需要Hibernate了解JTAPlatformTransactionManager

 

When Hibernate is not configured with any awareness of the JTA PlatformTransactionManager, the following events occur when a JTA transaction commits:

Hibernate没有配置任何JTAPlatformTransactionManager时,下面的事件当JTA事务提交时发生:

 

    The JTA transaction commits.

JTA事务提交。

    Springs JtaTransactionManager is synchronized to the JTA transaction, so it is called back through an afterCompletion callback by the JTA transaction manager.

springJtaTransactionManager是同步的对于JTA事务,因此可以被回调通过JTA的事务管理器的afterCompletion回调。

    Among other activities, this synchronization can trigger a callback by Spring to Hibernate, through Hibernates afterTransactionCompletion callback (used to clear the Hibernate cache), followed by an explicit close() call on the Hibernate Session, which causes Hibernate to attempt to close() the JDBC Connection.

在其他活动中,这些同步可以截获spring对于Hibernate的回调,通过HibernateafterTransactionCompletion回调(使用清理Hibernate的缓存),或许明确使用close方法调用对于Hibernatesession,可以使得Hibernate调用JDBC连接的close方法。

    In some environments, this Connection.close() call then triggers the warning or error, as the application server no longer considers the Connection usable at all, because the transaction has already been committed.

在一些环境中,这个Connection.close方法会引起警告或错误,作为应用服务器不需要考虑连接的重用,因为事务已经被提交了。

 

When Hibernate is configured with awareness of the JTA PlatformTransactionManager, the following events occur when a JTA transaction commits:

Hibernate被配置了解了JTAPlatformTransactionManager,下面的事件当JTA事务提交时会发生:

 

    the JTA transaction is ready to commit.

JTA事务准备提交。

    Springs JtaTransactionManager is synchronized to the JTA transaction, so the transaction is called back through a beforeCompletion callback by the JTA transaction manager.

springJtaTransactionManager是同步的对于JTA事务,因此事务可以被回调通过JTA的事务管理器的beforeCompletion回调。

    Spring is aware that Hibernate itself is synchronized to the JTA transaction, and behaves differently than in the previous scenario. Assuming the Hibernate Session needs to be closed at all, Spring will close it now.

spring连接Hibernate本身是同步的对于JTA事务,并且和之前场景中的行为是不同的。假设HibernateSession需要关闭,spring将会在现在关闭。

    The JTA transaction commits.

JTA事务提交。

    Hibernate is synchronized to the JTA transaction, so the transaction is called back through an afterCompletion callback by the JTA transaction manager, and can properly clear its cache.

Hibernate是同步的对于JTA事务,因此事务被回调通过JTA事务管理器的afterCompletion回调方法,并且可以清除他的缓存。

 

20.4 JDO

 

Spring supports the standard JDO 2.0 and 2.1 APIs as data access strategy, following the same style as the Hibernate support. The corresponding integration classes reside in the org.springframework.orm.jdo package.

spring支持标准的JDO2.02.1API作为数据访问策略,符合相同的风格作为Hibernate的支持。相应的集成类在org.springframework.orm.jdo包中。

 

20.4.1 PersistenceManagerFactory setup

PersistenceManagerFactory的设置

 

Spring provides a LocalPersistenceManagerFactoryBean class that allows you to define a local JDO PersistenceManagerFactory within a Spring application context:

spring提供了一个LocalPersistenceManagerFactoryBean类允许你来定义一个本地的JDOPersistenceManagerFactory通过spring的应用上下文:

 

<beans>

 

    <bean id="myPmf" class="org.springframework.orm.jdo.LocalPersistenceManagerFactoryBean">

        <property name="configLocation" value="classpath:kodo.properties"/>

    </bean>

 

</beans>

 

Alternatively, you can set up a PersistenceManagerFactory through direct instantiation of a PersistenceManagerFactory implementation class. A JDO PersistenceManagerFactory implementation class follows the JavaBeans pattern, just like a JDBC DataSource implementation class, which is a natural fit for a configuration that uses Spring. This setup style usually supports a Spring-defined JDBC DataSource, passed into the connectionFactory property. For example, for the open source JDO implementation DataNucleus (formerly JPOX) ( http://www.datanucleus.org/), this is the XML configuration of the PersistenceManagerFactory implementation:

作为代替,你可以设置一个PersistenceManagerFactory通过直接的PersistenceManagerFactory实现类。一个JDOPersistenceManagerFactory实现类符合JavaBean的模型,就像JDBC数据源实现类,是自然符合spring的配置的。这种设置风格通过支持spring定义的JDBC数据源,通过connectionFactory属性来传递。例如,对于开源的JDO实现DataNucleus(以前是JPOX)(http://www.datanucleus.org/),是PersistenceManagerFactory实现的xml配置。

 

<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="myPmf" class="org.datanucleus.jdo.JDOPersistenceManagerFactory" destroy-method="close">

    <property name="connectionFactory" ref="dataSource"/>

    <property name="nontransactionalRead" value="true"/>

 </bean>

 

</beans>

 

You can also set up JDO PersistenceManagerFactory in the JNDI environment of a Java EE application server, usually through the JCA connector provided by the particular JDO implementation. Springs standard JndiObjectFactoryBean or <jee:jndi-lookup> can be used to retrieve and expose such a PersistenceManagerFactory. However, outside an EJB context, no real benefit exists in holding the PersistenceManagerFactory in JNDI: only choose such a setup for a good reason. See Section 20.3.6, Comparing container-managed and locally defined resourcesfor a discussion; the arguments there apply to JDO as well.

你也可以设置JDOPersistenceManagerFactoryJNDI环境作为JavaEE的应用服务器,JCA连接器通过特定的JDO实现来提供。spring的标准JndiObjectFactoryBean<jee:jndi-lookup>可以被使用来获得并暴露这样的PersistenceManagerFactory。然而你,在EJB上下文之外,没有实际的好处存在来通过JNDI获取PersistenceManagerFactory:只有选择这样一个设置才是好的。见20.3.6节,“比较容器管理和本地定义资源”中的讨论,参数应用到JDO就可以。

 

20.4.2 Implementing DAOs based on the plain JDO API

基于普通的JDOAPI实现DAO

 

DAOs can also be written directly against plain JDO API, without any Spring dependencies, by using an injected PersistenceManagerFactory. The following is an example of a corresponding DAO implementation:

DAO可以使用普通的JDOAPI来完成,不需要spring的依赖,通过使用注入PersistenceManagerFactory。下面是一个例子有关DAO的实现:

 

public class ProductDaoImpl implements ProductDao {

 

    private PersistenceManagerFactory persistenceManagerFactory;

 

    public void setPersistenceManagerFactory(PersistenceManagerFactory pmf) {

        this.persistenceManagerFactory = pmf;

    }

 

    public Collection loadProductsByCategory(String category) {

        PersistenceManager pm = this.persistenceManagerFactory.getPersistenceManager();

        try {

            Query query = pm.newQuery(Product.class, "category = pCategory");

            query.declareParameters("String pCategory");

            return query.execute(category);

        }

        finally {

            pm.close();

        }

    }

}

 

<beans>

 

    <bean id="myProductDao" class="product.ProductDaoImpl">

        <property name="persistenceManagerFactory" ref="myPmf"/>

    </bean>

 

</beans>

 

The main problem with such DAOs is that they always get a new PersistenceManager from the factory. To access a Spring-managed transactional PersistenceManager, define a TransactionAwarePersistenceManagerFactoryProxy (as included in Spring) in front of your target PersistenceManagerFactory, then passing a reference to that proxy into your DAOs as in the following example:

这里主要的问题是这样的DAO会获得一个来自工程的新的PersistenceManager。为了访问spring管理的事务PersistenceManager,定义一个TransactionAwarePersistenceManagerFactoryProxy(包括在spring中)在你的目标PersistenceManagerFactory之前,然后传递一个代理的引用到你的DAO中如下面的例子:

 

<beans>

 

    <bean id="myPmfProxy"

            class="org.springframework.orm.jdo.TransactionAwarePersistenceManagerFactoryProxy">

        <property name="targetPersistenceManagerFactory" ref="myPmf"/>

    </bean>

 

    <bean id="myProductDao" class="product.ProductDaoImpl">

        <property name="persistenceManagerFactory" ref="myPmfProxy"/>

    </bean>

 

</beans>

 

Your data access code will receive a transactional PersistenceManager (if any) from the PersistenceManagerFactory.getPersistenceManager() method that it calls. The latter method call goes through the proxy, which first checks for a current transactional PersistenceManager before getting a new one from the factory. Any close() calls on the PersistenceManager are ignored in case of a transactional PersistenceManager.

你的数据访问代码将获得一个事务PersistenceManager(如果可以的话)来自PersistenceManagerFactory.getPersistenceManager方法。后面的方法调用通过代理,首先会检查当前的事务PersistenceManager在获得一个来自工程的新的之前。任何close的调用对于PersistenceManager被忽略由于事务的PersistenceManager

 

If your data access code always runs within an active transaction (or at least within active transaction synchronization), it is safe to omit the PersistenceManager.close() call and thus the entire finally block, which you might do to keep your DAO implementations concise:

如果你的数据访问代码通过一个激活事务来运行(或至少激活事务同步),省略PersistenceManager.close()调用是安全的包括整个finally块中,你可以保持DAO实现的简洁:

 

public class ProductDaoImpl implements ProductDao {

 

    private PersistenceManagerFactory persistenceManagerFactory;

 

    public void setPersistenceManagerFactory(PersistenceManagerFactory pmf) {

        this.persistenceManagerFactory = pmf;

    }

 

    public Collection loadProductsByCategory(String category) {

        PersistenceManager pm = this.persistenceManagerFactory.getPersistenceManager();

        Query query = pm.newQuery(Product.class, "category = pCategory");

        query.declareParameters("String pCategory");

        return query.execute(category);

    }

}

 

With such DAOs that rely on active transactions, it is recommended that you enforce active transactions through turning off TransactionAwarePersistenceManagerFactoryProxys `allowCreate flag:

这样的DAO依赖激活事务,推荐你强制激活事务通过关闭TransactionAwarePersistenceManagerFactoryProxysallowCreate标志:

 

<beans>

 

    <bean id="myPmfProxy"

            class="org.springframework.orm.jdo.TransactionAwarePersistenceManagerFactoryProxy">

        <property name="targetPersistenceManagerFactory" ref="myPmf"/>

        <property name="allowCreate" value="false"/>

    </bean>

 

    <bean id="myProductDao" class="product.ProductDaoImpl">

        <property name="persistenceManagerFactory" ref="myPmfProxy"/>

    </bean>

 

</beans>

 

The main advantage of this DAO style is that it depends on JDO API only; no import of any Spring class is required. This is of course appealing from a non-invasiveness perspective, and might feel more natural to JDO developers.

这个DAO风格的主要好处是他只依赖JDOAPI,不需要导入任何spring的依赖库。这当然符合没有侵入的风格,并且将更加自然对于JDO的开发者。

 

However, the DAO throws plain JDOException (which is unchecked, so does not have to be declared or caught), which means that callers can only treat exceptions as fatal, unless you want to depend on JDOs own exception structure. Catching specific causes such as an optimistic locking failure is not possible without tying the caller to the implementation strategy. This trade off might be acceptable to applications that are strongly JDO-based and/or do not need any special exception treatment.

然而,dao抛出普通的JDOException(是非检查的,不需要你定义或捕获),意味着调用者只需要处理致命这样的异常,除非你希望依赖JDO的异常结构。捕获特定的异常例如一个乐观锁失败是不可能的除非绑定调用者和实现策略。这种权衡对于应用时基于JDO不需要特定的异常处理。

 

In summary, you can DAOs based on the plain JDO API, and they can still participate in Spring-managed transactions. This strategy might appeal to you if you are already familiar with JDO. However, such DAOs throw plain JDOException, and you would have to convert explicitly to Springs DataAccessException (if desired).

总结一下,你可以让DAO基于普通的JDOAPI,并且他们可以参与spring管理的事务。这种策略可以使用于你如果你十分熟悉JDO。然而,这样的DAO会抛出普通的JDOException并且你必须将其明确转换为springDataAccessException(如果期望这么做)。

 

20.4.3 Transaction management

事务管理

 

[Note]

注意

 

You are strongly encouraged to read Section 17.5, Declarative transaction managementif you have not done so, to get a more detailed coverage of Springs declarative transaction support.

我们建议你阅读17.5节,“声明式事务管理”如果你没有这么做,为了获得更多有关spring的声明式事务管理的支持。

 

To execute service operations within transactions, you can use Springs common declarative transaction facilities. For example:

为了执行带有事务的服务操作,你可以使用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.xsd

        http://www.springframework.org/schema/tx

        http://www.springframework.org/schema/tx/spring-tx.xsd

        http://www.springframework.org/schema/aop

        http://www.springframework.org/schema/aop/spring-aop.xsd">

 

    <bean id="myTxManager" class="org.springframework.orm.jdo.JdoTransactionManager">

        <property name="persistenceManagerFactory" ref="myPmf"/>

    </bean>

 

    <bean id="myProductService" class="product.ProductServiceImpl">

        <property name="productDao" ref="myProductDao"/>

    </bean>

 

    <tx:advice id="txAdvice" transaction-manager="txManager">

        <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>

 

    <aop:config>

        <aop:pointcut id="productServiceMethods"

                expression="execution(* product.ProductService.*(..))"/>

        <aop:advisor advice-ref="txAdvice" pointcut-ref="productServiceMethods"/>

    </aop:config>

 

</beans>

 

JDO requires an active transaction to modify a persistent object. The non-transactional flush concept does not exist in JDO, in contrast to Hibernate. For this reason, you need to set up the chosen JDO implementation for a specific environment. Specifically, you need to set it up explicitly for JTA synchronization, to detect an active JTA transaction itself. This is not necessary for local transactions as performed by Springs JdoTransactionManager, but it is necessary to participate in JTA transactions, whether driven by Springs JtaTransactionManager or by EJB CMT and plain JTA.

JDO要求一个激活事务来修改一个持久化object。非事务的刷新概念不存在于JDO中,而在Hibernate中存在。由于这种原因,你需要设置选择JDO实现对于特定的环境。特定的,你需要明确设置对于JTA的同步,为了检测激活JTA事务本身。作为springJdoTransactionManager来说这不是必须的对于本地的事务,不管是基于springJtaTransactionManagerEJB CMT和普通的JTA

 

JdoTransactionManager is capable of exposing a JDO transaction to JDBC access code that accesses the same JDBC DataSource, provided that the registered JdoDialect supports retrieval of the underlying JDBC Connection. This is the case for JDBC-based JDO 2.0 implementations by default.

JdoTransactionManager可以暴露一个JDO事务对于JDBC访问代码来访问相同的JDBC数据源,提供注册的JdoDialect支持恢复底层的JDBC连接。这是由于基于JDBCJDO2.0实现是默认的。

 

20.4.4 JdoDialect

 

As an advanced feature, both LocalPersistenceManagerFactoryBean and JdoTransactionManager support a custom JdoDialect that can be passed into the jdoDialect bean property. Using a JdoDialect implementation, you can enable advanced features supported by Spring, usually in a vendor-specific manner:

作为高级的特性,LocalPersistenceManagerFactoryBeanJdoTransactionManager支持一个自定义的JdoDialect可以传递通过jdoDialectbean属性。使用JdoDialect的实现,你可以允许高级的spring的特性支持,通常以特定供应商的方式。

 

    Applying specific transaction semantics such as custom isolation level or transaction timeout

应用特定事务语义例如自定义隔离级别或事务超时

    Retrieving the transactional JDBC Connection for exposure to JDBC-based DAOs

获得事务的JDBC连接为了暴露给基于JDBCDAO

    Applying query timeouts, which are automatically calculated from Spring-managed transaction timeouts

应用查询超时,可以自动计算来自spring管理的事务超时

    Eagerly flushing a PersistenceManager, to make transactional changes visible to JDBC-based data access code

强烈刷新PersistenceManager为了使得事务改变对于基于JDBC的数据访问代码可见

    Advanced translation of JDOExceptions to Spring DataAccessExceptions

对于springDataAccessExceptionsJDOExceptions的高级翻译

 

See the JdoDialect javadocs for more details on its operations and how to use them within Springs JDO support.

详见JdoDialectjavadocs关于他的操作及如何使用springJDO支持。

 

20.5 JPA

 

The Spring JPA, available under the org.springframework.orm.jpa package, offers comprehensive support for the Java Persistence API in a similar manner to the integration with Hibernate or JDO, while being aware of the underlying implementation in order to provide additional features.

springJPAorg.springframework.orm.jpa包中,提供了复杂的支持对于Java的持久化API在相同的情况通过HibernateJDO,可以被实现已知为了提供额外的特性。

 

20.5.1 Three options for JPA setup in a Spring environment

对于在spring环境中的JPA设置选项

 

The Spring JPA support offers three ways of setting up the JPA EntityManagerFactory that will be used by the application to obtain an entity manager.

springJPA支持提供了三种设置方式对于EntityManagerFactory可以被应用来使用来获得一个实例管理器。

 

LocalEntityManagerFactoryBean

 

[Note]

注意

 

Only use this option in simple deployment environments such as stand-alone applications and integration tests.

只用使用这个选项在简单的部署环境例如独立的应用或集成测试中。

 

The LocalEntityManagerFactoryBean creates an EntityManagerFactory suitable for simple deployment environments where the application uses only JPA for data access. The factory bean uses the JPA PersistenceProvider autodetection mechanism (according to JPAs Java SE bootstrapping) and, in most cases, requires you to specify only the persistence unit name:

LocalEntityManagerFactoryBean创建一个EntityManagerFactory使用于简单的部署环境当应用只使用JPA对于数据访问。工厂bean使用JPAPersistenceProvider自动探测策略(遵循JPAJavaSE的启动)并且,在大部分情况,要求你来指定持久化单元名字:

 

<beans>

    <bean id="myEmf" class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">

        <property name="persistenceUnitName" value="myPersistenceUnit"/>

    </bean>

</beans>

 

This form of JPA deployment is the simplest and the most limited. You cannot refer to an existing JDBC DataSource bean definition and no support for global transactions exists. Furthermore, weaving (byte-code transformation) of persistent classes is provider-specific, often requiring a specific JVM agent to specified on startup. This option is sufficient only for stand-alone applications and test environments, for which the JPA specification is designed.

这种JPA部署的形式是最简单的也是最多限制的。你不能引用已有的JDBC数据源的bean定义和不支持全局的事务支持。此外,处理(二进制转换)持久化类是特定,需要一个特殊的JVM代理在启动时指定。这个选项对于独立的应用和测试环境是足够的,特定于对于JPA的设计。

 

Obtaining an EntityManagerFactory from JNDI

JNDI中获得一个EntityManagerFactory

 

[Note]

注意

 

Use this option when deploying to a Java EE 5 server. Check your servers documentation on how to deploy a custom JPA provider into your server, allowing for a different provider than the servers default.

当部署在JavaEE5服务器的时候使用这个选项。检查你的服务器文档关于如何部署一个自定义的JPA的提供者对于你的服务器,允许你使用不同的提供而不只是使用服务器默认的。

 

Obtaining an EntityManagerFactory from JNDI (for example in a Java EE 5 environment), is simply a matter of changing the XML configuration:

JNDI中获得一个EntityManagerFactory(例如在JavaEE5的环境中),是简单的只要改变xml的配置:

 

<beans>

    <jee:jndi-lookup id="myEmf" jndi-name="persistence/myPersistenceUnit"/>

</beans>

 

This action assumes standard Java EE 5 bootstrapping: the Java EE server autodetects persistence units (in effect, META-INF/persistence.xml files in application jars) and persistence-unit-ref entries in the Java EE deployment descriptor (for example, web.xml) and defines environment naming context locations for those persistence units.

这个行为假设标准的JavaEE5引导:JavaEE服务器自动探测持久化单元(实际上,在应用jar中的META-INF/persistence.xml文件)并且持久化单元引用实体在JavaEE的部署描述符(例如,web.xml)并且定义环境命名上下文位置对于这些持久化单元。

 

In such a scenario, the entire persistence unit deployment, including the weaving (byte-code transformation) of persistent classes, is up to the Java EE server. The JDBC DataSource is defined through a JNDI location in the META-INF/persistence.xml file; EntityManager transactions are integrated with the servers JTA subsystem. Spring merely uses the obtained EntityManagerFactory, passing it on to application objects through dependency injection, and managing transactions for the persistence unit, typically through JtaTransactionManager.

在这种场景中,整个持久化单元部署,包括处理(二进制转换)持久化类,对于JavaEE服务器。JDBC数据源被定义通过JNDI的位置在META-INF/persistence.xml文件中;EntityManager事务被集成到服务器的JTA子系统中。spring很少使用获得EntityManagerFactory,可以传递给应用object通过依赖注入并且管理事务对于持久化单元,通常通过JtaTransactionManager

 

If multiple persistence units are used in the same application, the bean names of such JNDI-retrieved persistence units should match the persistence unit names that the application uses to refer to them, for example, in @PersistenceUnit and @PersistenceContext annotations.

如果多个持久化单元被使用在相同的应用中,bean的名字例如JNDI的单元应当匹配持久化单元名字当应用引用他们的时候,例如,在@PersistenceUnit@PersistenceContext注解中。

 

LocalContainerEntityManagerFactoryBean

 

[Note]

注意

 

Use this option for full JPA capabilities in a Spring-based application environment. This includes web containers such as Tomcat as well as stand-alone applications and integration tests with sophisticated persistence requirements.

在基于spring管理的应用环境使用这个选项对于全功能的JPA功能。这包括web容器例如Tomcat和独立的应用和集成测试包含负责的持久化请求。

 

The LocalContainerEntityManagerFactoryBean gives full control over EntityManagerFactory configuration and is appropriate for environments where fine-grained customization is required. The LocalContainerEntityManagerFactoryBean creates a PersistenceUnitInfo instance based on the persistence.xml file, the supplied dataSourceLookup strategy, and the specified loadTimeWeaver. It is thus possible to work with custom data sources outside of JNDI and to control the weaving process. The following example shows a typical bean definition for a LocalContainerEntityManagerFactoryBean:

LocalContainerEntityManagerFactoryBean给予了全面的控制对于EntityManagerFactory的配置并且适用于细粒度的自定义需求。LocalContainerEntityManagerFactoryBean创建一个PersistenceUnitInfo实例基于persistence.xml文件,提供dataSourceLookup策略并且指定loadTimeWeaver。可以使用自定义数据源工作在JNDI之外并且控制处理程序。下面的例子展示了一个典型的bean定义对于LocalContainerEntityManagerFactoryBean

 

<beans>

    <bean id="myEmf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">

        <property name="dataSource" ref="someDataSource"/>

        <property name="loadTimeWeaver">

            <bean class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver"/>

        </property>

    </bean>

</beans>

 

The following example shows a typical persistence.xml file:

下面的例子展示了一个典型的persistence.xml文件

 

<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="1.0">

    <persistence-unit name="myUnit" transaction-type="RESOURCE_LOCAL">

        <mapping-file>META-INF/orm.xml</mapping-file>

        <exclude-unlisted-classes/>

    </persistence-unit>

</persistence>

 

[Note]

注意

 

The <exclude-unlisted-classes/> shortcut indicates that no scanning for annotated entity classes is supposed to occur. An explicit 'true' value specified - <exclude-unlisted-classes>true</exclude-unlisted-classes/> - also means no scan. <exclude-unlisted-classes>false</exclude-unlisted-classes/> does trigger a scan; however, it is recommended to simply omit the exclude-unlisted-classes element if you want entity class scanning to occur.

<exclude-unlisted-classes/>简写展示了不在扫描注解实体类是支持的。一个冲突指定为true——<exclude-unlisted-classes>true</exclude-unlisted-classes/>————也意味着不会扫描。<exclude-unlisted-classes>false</exclude-unlisted-classes/>会引起扫描,然而,他不会简单的省略exclude-unlisted-classes元素如果你希望整个类被扫描。

 

Using the LocalContainerEntityManagerFactoryBean is the most powerful JPA setup option, allowing for flexible local configuration within the application. It supports links to an existing JDBC DataSource, supports both local and global transactions, and so on. However, it also imposes requirements on the runtime environment, such as the availability of a weaving-capable class loader if the persistence provider demands byte-code transformation.

使用LocalContainerEntityManagerFactoryBean是最有力的JPA设置选项,允许方便的本地配置对于应用。他支持一个已有的JDBC数据源,支持本地和全局事务等等。然而,他也需要运行时环境,例如可用的代码包裹类如果持久化提供通过二进制转换。

 

This option may conflict with the built-in JPA capabilities of a Java EE 5 server. In a full Java EE 5 environment, consider obtaining your EntityManagerFactory from JNDI. Alternatively, specify a custom persistenceXmlLocation on your LocalContainerEntityManagerFactoryBean definition, for example, META-INF/my-persistence.xml, and only include a descriptor with that name in your application jar files. Because the Java EE 5 server only looks for default META-INF/persistence.xml files, it ignores such custom persistence units and hence avoid conflicts with a Spring-driven JPA setup upfront. (This applies to Resin 3.1, for example.)

这个选项可能发生冲突在内置的JavaEE5服务器中内置的JPA功能。在全面的JavaEE5环境中,考虑从JNDI中获得你的EntityManagerFactory。作为替代,定义一个自定义的persistenceXmlLocation在你的LocalContainerEntityManagerFactoryBean定义中,例如,META-INF/my-persistence.xml,并且只包括一个描述符在你应用的jar文件的名字中。因为JavaEE5服务器只会寻找默认的META-INF/persistence.xml文件,他忽略这样的自定义持久化单元因此提前避免冲突和基于springJPA设置。(这适用于Resin3.1,作为例子。)

 

When is load-time weaving required?

什么时候需要加载时处理?

 

Not all JPA providers require a JVM agent ; Hibernate is an example of one that does not. If your provider does not require an agent or you have other alternatives, such as applying enhancements at build time through a custom compiler or an ant task, the load-time weaver should not be used.

并不是所有的JPA提供了一个JVM代理;Hibernate就是一个例子就是没有提供代理。如果你提供者没有需要一个代理或你有一个其他的选择,例如在构建时的应用增强通过一个自定义的编译器或一个ant认为,加载时处理不应被使用。

 

The LoadTimeWeaver interface is a Spring-provided class that allows JPA ClassTransformer instances to be plugged in a specific manner, depending whether the environment is a web container or application server. Hooking ClassTransformers through an agent typically is not efficient. The agents work against the entire virtual machine and inspect every class that is loaded, which is usually undesirable in a production server environment.

LoadTimeWeaver接口是spring提供的类允许JPAClassTransformer实例组装以特定的行为,依赖于环境是否是一个web容器或应用服务器。挂钩ClassTransformers通过一个代理通常是不够的。代理配合整个虚拟机工作并且检查每个加载的类,通常不会在生产环境中使用。

 

Spring provides a number of LoadTimeWeaver implementations for various environments, allowing ClassTransformer instances to be applied only per class loader and not per VM.

spring提供了一系列的LoadTimeWeaver实现对于不同的环境,允许ClassTransformer实例被应用于每个类加载器而不是每个虚拟机。

 

Refer to the section called Spring configurationin the AOP chapter for more insight regarding the LoadTimeWeaver implementations and their setup, either generic or customized to various platforms (such as Tomcat, WebLogic, GlassFish, Resin and JBoss).

引用的章节名字为spring配置”在AOP章节中关于更多检查LoadTimeWeaver的实现和他的启动,不管是通用还是自定义对于不同的平台(例如TomcatWebLogicGlassFishResinJBoss)。

 

As described in the aforementioned section, you can configure a context-wide LoadTimeWeaver using the @EnableLoadTimeWeaving annotation of context:load-time-weaver XML element. Such a global weaver is picked up by all JPA LocalContainerEntityManagerFactoryBeans automatically. This is the preferred way of setting up a load-time weaver, delivering autodetection of the platform (WebLogic, GlassFish, Tomcat, Resin, JBoss or VM agent) and automatic propagation of the weaver to all weaver-aware beans:

在之前的章节中描述过,你可以配置一个上下文的LoadTimeWeaver使用@EnableLoadTimeWeaving注解来自context:load-time-weaverxml元素。例如一个全局的处理器来自动获得JPALocalContainerEntityManagerFactoryBeans。这是一个推荐的方法来设置加载时处理器,发表平台的自动探测(WebLogicGlassFishTomcatResinJBoss或虚拟机代理)和自动处理器传播对于所有的处理器理解的bean

 

<context:load-time-weaver/>

<bean id="emf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">

    ...

</bean>

 

However, if needed, one can manually specify a dedicated weaver through the loadTimeWeaver property:

然而,如果需要,可以手动指定一个专用的处理器通过loadTimeWeaver属性:

 

<bean id="emf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">

    <property name="loadTimeWeaver">

        <bean class="org.springframework.instrument.classloading.ReflectiveLoadTimeWeaver"/>

    </property>

</bean>

 

No matter how the LTW is configured, using this technique, JPA applications relying on instrumentation can run in the target platform (ex: Tomcat) without needing an agent. This is important especially when the hosting applications rely on different JPA implementations because the JPA transformers are applied only at class loader level and thus are isolated from each other.

不管如何设置LTW,使用这种技术,JPA应用依赖的功能可以运行在目标平台(例如Tomcat)而不需要一个代理。这是很重要的当处理应用依赖于不同的JPA实现因为JPA转换被应用于类加载器级别和其他是隔离的。

 

Dealing with multiple persistence units

处理多个持久化单元

 

For applications that rely on multiple persistence units locations, stored in various JARS in the classpath, for example, Spring offers the PersistenceUnitManager to act as a central repository and to avoid the persistence units discovery process, which can be expensive. The default implementation allows multiple locations to be specified that are parsed and later retrieved through the persistence unit name. (By default, the classpath is searched for META-INF/persistence.xml files.)

对于应用他们依赖多个持久化单元的位置,存储在不同的JARSclasspath中,例如,spring提供了PersistenceUnitManager来处理一个中心的库并且避免持久化单元探测程序,可以被扩展。默认的实现允许多个位置被指定来解析和后续接收持久化单元名。(默认,classpath被查找对于META-INF/persistence.xml文件。)

 

<bean id="pum" class="org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager">

    <property name="persistenceXmlLocations">

        <list>

            <value>org/springframework/orm/jpa/domain/persistence-multi.xml</value>

            <value>classpath:/my/package/**/custom-persistence.xml</value>

            <value>classpath*:META-INF/persistence.xml</value>

        </list>

    </property>

    <property name="dataSources">

        <map>

            <entry key="localDataSource" value-ref="local-db"/>

            <entry key="remoteDataSource" value-ref="remote-db"/>

        </map>

    </property>

    <!-- if no datasource is specified, use this one -->

    <property name="defaultDataSource" ref="remoteDataSource"/>

</bean>

 

<bean id="emf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">

    <property name="persistenceUnitManager" ref="pum"/>

    <property name="persistenceUnitName" value="myCustomUnit"/>

</bean>

 

The default implementation allows customization of the PersistenceUnitInfo instances, before they are fed to the JPA provider, declaratively through its properties, which affect all hosted units, or programmatically, through the PersistenceUnitPostProcessor, which allows persistence unit selection. If no PersistenceUnitManager is specified, one is created and used internally by LocalContainerEntityManagerFactoryBean.

默认的实现允许PersistenceUnitInfo实例的自定义,之前他们可以被处理通过JPA的提供者,通过属性来定义,影响所有的持有单元,或编程通过PersistenceUnitPostProcessor,允许持久化单元选择。如果没有指定PersistenceUnitManager,可以创建并使用内置的LocalContainerEntityManagerFactoryBean

 

20.5.2 Implementing DAOs based on plain JPA

基于普通的JPA实现DAO

 

[Note]

注意

 

Although EntityManagerFactory instances are thread-safe, EntityManager instances are not. The injected JPA EntityManager behaves like an EntityManager fetched from an application servers JNDI environment, as defined by the JPA specification. It delegates all calls to the current transactional EntityManager, if any; otherwise, it falls back to a newly created EntityManager per operation, in effect making its usage thread-safe.

尽管EntityManagerFactory实例是线程安全的,但是EntityManager实例却不是。注入JPAEntityManager行为类似于一个EntityManager从一个应用服务器的JNDI环境中获取,通过JPA规范来定义。他代表所有调用当前的事务EntityManager,此外,他回调一个新创建的EntityManager在每次的操作中,使得他是线程安全的。

 

It is possible to write code against the plain JPA without any Spring dependencies, by using an injected EntityManagerFactory or EntityManager. Spring can understand @PersistenceUnit and @PersistenceContext annotations both at field and method level if a PersistenceAnnotationBeanPostProcessor is enabled. A plain JPA DAO implementation using the @PersistenceUnit annotation might look like this:

可以写代码使用普通的JPA而不依赖于spring,通过使用EntityManagerFactoryEntityManagerspring可以理解@PersistenceUnit@PersistenceContext注解在field和方法级别如果允许PersistenceAnnotationBeanPostProcessor的话。一个普通的JPADAO实现使用@PersistenceUnit注解类似于:

 

public class ProductDaoImpl implements ProductDao {

 

    private EntityManagerFactory emf;

 

    @PersistenceUnit

    public void setEntityManagerFactory(EntityManagerFactory emf) {

        this.emf = emf;

    }

 

    public Collection loadProductsByCategory(String category) {

        EntityManager em = this.emf.createEntityManager();

        try {

            Query query = em.createQuery("from Product as p where p.category = ?1");

            query.setParameter(1, category);

            return query.getResultList();

        }

        finally {

            if (em != null) {

                em.close();

            }

        }

    }

}

 

The DAO above has no dependency on Spring and still fits nicely into a Spring application context. Moreover, the DAO takes advantage of annotations to require the injection of the default EntityManagerFactory:

上面的DAO没有依赖spring并且依然可以用在spring的应用上下文中。此外,dao使用了注解的优点需要注入默认的EntityManagerFactory

 

<beans>

 

    <!-- bean post-processor for JPA annotations -->

    <bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/>

 

    <bean id="myProductDao" class="product.ProductDaoImpl"/>

 

</beans>

 

As an alternative to defining a PersistenceAnnotationBeanPostProcessor explicitly, consider using the Spring context:annotation-config XML element in your application context configuration. Doing so automatically registers all Spring standard post-processors for annotation-based configuration, including CommonAnnotationBeanPostProcessor and so on.

作为替代明确定义一个PersistenceAnnotationBeanPostProcessor,考虑使用springcontext:annotation-configxml元素在你应用上下文的配置中。这样可以自动注册所有spring标准的后处理器对于基于注解的配置,包括CommonAnnotationBeanPostProcessor等等。

 

<beans>

 

    <!-- post-processors for all standard config annotations -->

    <context:annotation-config/>

 

    <bean id="myProductDao" class="product.ProductDaoImpl"/>

 

</beans>

 

The main problem with such a DAO is that it always creates a new EntityManager through the factory. You can avoid this by requesting a transactional EntityManager (also called "shared EntityManager" because it is a shared, thread-safe proxy for the actual transactional EntityManager) to be injected instead of the factory:

主要的问题关于dao是会经常创建一个新的EntityManager通过工厂。你可以避免这个问题通过请求一个事务EntityManager(也叫做"shared EntityManager"因为他是共享的、线程安全的代理对于实际的事务EntityManager)可以被注入到工厂中:

 

public class ProductDaoImpl implements ProductDao {

 

    @PersistenceContext

    private EntityManager em;

 

    public Collection loadProductsByCategory(String category) {

        Query query = em.createQuery("from Product as p where p.category = :category");

        query.setParameter("category", category);

        return query.getResultList();

    }

}

 

The @PersistenceContext annotation has an optional attribute type, which defaults to PersistenceContextType.TRANSACTION. This default is what you need to receive a shared EntityManager proxy. The alternative, PersistenceContextType.EXTENDED, is a completely different affair: This results in a so-called extended EntityManager, which is not thread-safe and hence must not be used in a concurrently accessed component such as a Spring-managed singleton bean. Extended EntityManagers are only supposed to be used in stateful components that, for example, reside in a session, with the lifecycle of the EntityManager not tied to a current transaction but rather being completely up to the application.

@PersistenceContext注解有一个可选属性type,默认值是PersistenceContextType.TRANSACTION。默认是你需要收到一个共享的EntityManager代理。另外一个选项是PersistenceContextType.EXTENDED,一个完全不同的方式:也叫做扩展EntityManager,不是线程安全的,所以必须安全的访问例如作为spring管理的单例bean。扩展EntityManager只支持使用在有状态的组件,例如,在session中跟随EntityManager的生命周期但是没有绑定到当前的事务而是被应用所管理。

 

Method- and field-level Injection

方法和field级别的注入

 

Annotations that indicate dependency injections (such as @PersistenceUnit and @PersistenceContext) can be applied on field or methods inside a class, hence the expressions method-level injection and field-level injection. Field-level annotations are concise and easier to use while method-level allows for further processing of the injected dependency. In both cases the member visibility (public, protected, private) does not matter.

注解指示依赖注入(例如@PersistenceUnit@PersistenceContext)可以被应用于类中的field或方法,因此表达式方法级别注入和field界别的注入。field级别的注入是简明的并且方便使用而方法级别的注入允许对依赖注入进行更进一步的处理。两种方式都是可见的(publicprotectedprivate)都可以。

 

What about class-level annotations?

类级别的注解如何?

 

On the Java EE 5 platform, they are used for dependency declaration and not for resource injection.

JavaEE5平台,他们被使用依赖定义而不是资源注入。

 

The injected EntityManager is Spring-managed (aware of the ongoing transaction). It is important to note that even though the new DAO implementation uses method level injection of an EntityManager instead of an EntityManagerFactory, no change is required in the application context XML due to annotation usage.

注入EntityManagerspring管理的(包括不明的事务)。注意到这点是重要的通过新的dao实现使用方法级别的注入对于EntityManager代替EntityManagerFactory,对于应用上下文的xml是不需要改变的由于注解的使用。

 

The main advantage of this DAO style is that it only depends on Java Persistence API; no import of any Spring class is required. Moreover, as the JPA annotations are understood, the injections are applied automatically by the Spring container. This is appealing from a non-invasiveness perspective, and might feel more natural to JPA developers.

这种dao风格主要的优势是只依赖于Java持久化API,没有导入任何spring的类。此外,作为JPA注解是易于理解的,注入由spring的容器自动完成。这符合不侵入的方式,并且可以对于JPA的开发者来说是很自然的。

 

20.5.3 Transaction Management

事务管理

 

[Note]

注意

 

You are strongly encouraged to read Section 17.5, Declarative transaction managementif you have not done so, to get a more detailed coverage of Springs declarative transaction support.

我们强烈建议你阅读17.5节,“声明式事务管理”如果你没有读过的话,为了获得有关spring对于声明式事务管理更多的细节描述。

 

To execute service operations within transactions, you can use Springs common declarative transaction facilities. For example:

为了执行服务操作通过事务,你可以使用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.xsd

        http://www.springframework.org/schema/tx

        http://www.springframework.org/schema/tx/spring-tx.xsd

        http://www.springframework.org/schema/aop

        http://www.springframework.org/schema/aop/spring-aop.xsd">

 

    <bean id="myTxManager" class="org.springframework.orm.jpa.JpaTransactionManager">

        <property name="entityManagerFactory" ref="myEmf"/>

    </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>

 

Spring JPA allows a configured JpaTransactionManager to expose a JPA transaction to JDBC access code that accesses the same JDBC DataSource, provided that the registered JpaDialect supports retrieval of the underlying JDBC Connection. Out of the box, Spring provides dialects for the EclipseLink, Hibernate and OpenJPA JPA implementations. See the next section for details on the JpaDialect mechanism.

springJPA允许一个配置JpaTransactionManager来获得JPA事务对于JDBC访问代码访问相同的JDBC数据源,提供了注册的JpaDialect来支持获得底层的JDBC连接。之外,spring提供了支持对于EclipseLinkHibernateOpenJPAJPA实现。参见下一节中有关JpaDialect策略的细节。

 

20.5.4 JpaDialect

 

As an advanced feature JpaTransactionManager and subclasses of AbstractEntityManagerFactoryBean support a custom JpaDialect, to be passed into the jpaDialect bean property. A JpaDialect implementation can enable some advanced features supported by Spring, usually in a vendor-specific manner:

一个高级特性JpaTransactionManagerAbstractEntityManagerFactoryBean的子类支持自定义的JpaDialect,可以传递给jpaDialectbean属性。一个JpaDialect实现可以允许spring支持的一些高级的特性,通常在一个特定供应商的情况。

 

    Applying specific transaction semantics such as custom isolation level or transaction timeout)

应用特定的事务语义例如一个自定义的隔离级别或事务超时

    Retrieving the transactional JDBC Connection for exposure to JDBC-based DAOs)

获得事务的JDBC连接对于暴露基于JDBCdao

    Advanced translation of PersistenceExceptions to Spring DataAccessExceptions

高级的翻译对于PersistenceExceptions异常为springDataAccessExceptions

 

This is particularly valuable for special transaction semantics and for advanced translation of exception. The default implementation used ( DefaultJpaDialect) does not provide any special capabilities and if the above features are required, you have to specify the appropriate dialect.

这是特殊的值对于特定的事务语义和高级的异常翻译。默认的实现使用(DefaultJpaDialect)没有支持任何特定的功能如果上面的特性被要求的话,你必须指定适当的方言。

 

See the JpaDialect javadocs for more details of its operations and how they are used within Springs JPA support.

参见JpaDialectjavad来了解更多相关的操作和如何使用springJPA支持。

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1. 简介 1.1. 概览 1.2. 使用场景 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 切面的支持 2.4. 中间层 2.4.1. 在XML里更为简单的声明性事务配置 2.4.2. JPA 2.4.3. 异步的JMS 2.4.4. JDBC 2.5. Web层 2.5.1. Spring MVC的表单标签库 2.5.2. Spring MVC合理的默认值 2.5.3. Portlet 框架 2.6. 其他特性 2.6.1. 动态语言支持 2.6.2. JMX 2.6 .3. 任务规划 2.6.4. 对Java 5(Tiger)的支持 2.7. 移植到Spring 2.0 2.7.1. 一些变化 2.7.1.1. Jar包 2.7.1.2. XML配置 2.7.1.3. Deprecated的类和方法 2.7.1.4. Apache OJB 2.7.1.5. iBatis 2.8. 更新的样例应用 2.9. 改进的文档 I. 核心技术 3. 控制反转容器 3.1. 简介 3.2. 容器和bean的基本原理 3.2.1. 容器 3.2.1.1. 配置元数据 3.2.2. 实例化容器 3.2.2.1. 组成基于XML配置元数据 3.2.3. 多种bean 3.2.3.1. 命名bean 3.2.3.2. 实例化bean 3.2.4. 使用容器 3.3. 依赖 3.3.1. 注入依赖 3.3.1.1. Setter注入 3.3.1.2. 构造器注入 3.3.1.3. 一些例子 3.3.2. 构造器参数的解析 3.3.2.1. 构造器参数类型匹配 3.3.2.2. 构造器参数的索引 3.3.3. bean属性及构造器参数详解 3.3.3.1. 直接量(基本类型、Strings类型等。) 3.3.3.2. 引用其它的bean(协作者) 3.3.3.3. 内部bean 3.3.3.4. 集合 3.3.3.5. Nulls 3.3.3.6. XML-based configuration metadata shortcuts 3.3.3.7. 组合属性名称 3.3.4. 使用depends-on 3.3.5. 延迟初始化bean 3.3.6. 自动装配(autowire)协作者 3.3.6.1. 设置Bean使自动装配失效 3.3.7. 依赖检查 3.3.8. 方法注入 3.3.8.1. Lookup方法注入 3.3.8.2. 自定义方法的替代方案 3.4. bean的作用域 3.4.1. Singleton作用域 3.4.2. Prototype作用域 3.4.3. 其他作用域 3.4.3.1. 初始化web配置 3.4.3.2. Request作用域 3.4.3.3. Session作用域 3.4.3.4. global session作用域 3.4.3.5. 作用域bean与依赖 3.4.4. 自定义作用域 3.5. 定制bean特性 3.5.1. Lifecycle接口 3.5.1.1. 初始化回调 3.5.1.2. 析构回调 3.5.2. 了解自己 3.5.2.1. BeanFactoryAware 3.5.2.2. BeanNameAware 3.6. bean定义的继承 3.7. 容器扩展点 3.7.1. 用BeanPostProcessor定制bean 3.7.1.1. 使用BeanPostProcessor的Hello World示例 3.7.1.2. RequiredAnnotationBeanPostProcessor示例 3.7.2. 用BeanFactoryPostProcessor定制配置元数据 3.7.2.1. PropertyPlaceholderConfigurer示例 3.7.2.2. PropertyOverrideConfigurer示例 3.7.3. 使用FactoryBean定制实例化逻辑 3.8. ApplicationContext 3.8.1. 利用MessageSource实现国际化 3.8.2. 事件 3.8.3. 底层资源的访问 3.8.4. ApplicationContext在WEB应用中的实例化 3.9. 粘合代码和可怕的singleton 3.9.1. 使用Singleton-helper类 4. 资源 4.1. 简介 4.2. Resource 接口 4.3. 内置 Resource 实现 4.3.1. UrlResource 4.3.2. ClassPathResource 4.3.3. FileSystemResource 4.3.4. ServletContextResource 4.3.5. InputStreamResource 4.3.6. ByteArrayResource 4.4. ResourceLoader 4.5. ResourceLoaderAware 接口 4.6. 把Resource作为属性来配置 4.7. Application context 和Resource 路径 4.7.1. 构造application context 4.7.1.1. 创建 ClassPathXmlApplicationContext 实例 - 简介 4.7.2. Application context构造器中资源路径的通配符 4.7.2.1. Ant风格的pattern 4.7.2.2. classpath*: 前缀 4.7.2.3. 其他关于通配符的说明 4.7.3. FileSystemResource 提示 5. 校验,数据绑定,BeanWrapper,与属性编辑器 5.1. 简介 5.2. 使用Spring的Validator接口进行校验 5.3. 从错误代码到错误信息 5.4. Bean处理和BeanWrapper 5.4.1. 设置和获取属性值以及嵌套属性 5.4.2. 内建的PropertyEditor实现 5.4.2.1. 注册用户自定义的PropertyEditor 6. 使用Spring进行面向切面编程(AOP) 6.1. 简介 6.1.1. AOP概念 6.1.2. Spring AOP的功能和目标 6.1.3. Spring的AOP代理 6.2. @AspectJ支持 6.2.1. 启用@AspectJ支持 6.2.2. 声明一个切面 6.2.3. 声明一个切入点(pointcut) 6.2.3.1. 切入点指定者的支持 6.2.3.2. 合并切入点表达式 6.2.3.3. 共享常见的切入点(pointcut)定义 6.2.3.4. 示例 6.2.4. 声明通知 6.2.4.1. 前置通知(Before advice) 6.2.4.2. 返回后通知(After returning advice) 6.2.4.3. 抛出后通知(After throwing advice) 6.2.4.4. 后通知(After (finally) advice) 6.2.4.5. 环绕通知(Around Advice) 6.2.4.6. 通知参数(Advice parameters) 6.2.4.7. 通知(Advice)顺序 6.2.5. 引入(Introductions) 6.2.6. 切面实例化模型 6.2.7. 例子 6.3. Schema-based AOP support 6.3.1. 声明一个切面 6.3.2. 声明一个切入点 6.3.3. 声明通知 6.3.3.1. 通知(Advice) 6.3.3.2. 返回后通知(After returning advice) 6.3.3.3. 抛出异常后通知(After throwing advice) 6.3.3.4. 后通知(After (finally) advice) 6.3.3.5. 通知 6.3.3.6. 通知参数 6.3.3.7. 通知顺序 6.3.4. 引入 6.3.5. 切面实例化模型 6.3.6. Advisors 6.3.7. 例子 6.4. AOP声明风格的选择 6.4.1. Spring AOP还是完全用AspectJ? 6.4.2. Spring AOP中使用@AspectJ还是XML? 6.5. 混合切面类型 6.6. 代理机制 6.7. 编程方式创建@AspectJ代理 6.8. 在Spring应用中使用AspectJ 6.8.1. 在Spring中使用AspectJ来为domain object进行依赖注入 6.8.1.1. @Configurable object的单元测试 6.8.1.2. 多application context情况下的处理 6.8.2. Spring中其他的AspectJ切面 6.8.3. 使用Spring IoC来配置AspectJ的切面 6.8.4. 在Spring应用中使用AspectJ Load-time weaving(LTW) 6.9. 其它资源 7. Spring AOP APIs 7.1. 简介 7.2. Spring中的切入点API 7.2.1. 概念 7.2.2. 切入点实施 7.2.3. AspectJ切入点表达式 7.2.4. 便利的切入点实现 7.2.4.1. 静态切入点 7.2.4.2. 动态切入点 7.2.5. 切入点的基类 7.2.6. 自定义切入点 7.3. Spring的通知API 7.3.1. 通知的生命周期 7.3.2. Spring里的通知类型 7.3.2.1. 拦截around通知 7.3.2.2. 前置通知 7.3.2.3. 异常通知 7.3.2.4. 后置通知 7.3.2.5. 引入通知 7.4. Spring里的advisor(Advisor) API 7.5. 使用ProxyFactoryBean创建AOP代理 7.5.1. 基础 7.5.2. JavaBean属性 7.5.3. 基于JDK和CGLIB的代理 7.5.4. 对接口进行代理 7.5.5. 对类进行代理 7.5.6. 使用“全局”advisor 7.6. 简化代理定义 7.7. 使用ProxyFactory通过编程创建AOP代理 7.8. 操作被通知对象 7.9. 使用“自动代理(autoproxy)”功能 7.9.1. 自动代理bean定义 7.9.1.1. BeanNameAutoProxyCreator 7.9.1.2. DefaultAdvisorAutoProxyCreator 7.9.1.3. AbstractAdvisorAutoProxyCreator 7.9.2. 使用元数据驱动的自动代理 7.10. 使用TargetSources 7.10.1. 热交换目标源 7.10.2. 池化目标源 7.10.3. 原型目标源 7.10.4. ThreadLocal目标源 7.11. 定义新的通知类型 7.12. 更多资源 8. 测试 8.1. 简介 8.2. 单元测试 8.3. 集成测试 8.3.1. Context管理和缓存 8.3.2. 测试fixture的依赖注入 8.3.3. 事务管理 8.3.4. 方便的变量 8.3.5. 示例 8.3.6. 运行集成测试 8.4. 更多资源 II. 中间层数据访问 9. 事务管理 9.1. 简介 9.2. 动机 9.3. 关键抽象 9.4. 使用资源同步的事务 9.4.1. 高层次方案 9.4.2. 低层次方案 9.4.3. TransactionAwareDataSourceProxy 9.5. 声明式事务管理 9.5.1. 理解Spring的声明式事务管理实现 9.5.2. 第一个例子 9.5.3. 回滚 9.5.4. 为不同的bean配置不同的事务语义 9.5.5. <tx:advice/> 有关的设置 9.5.6. 使用 @Transactional 9.5.6.1. @Transactional 有关的设置 9.5.7. 插入事务操作 9.5.8. 结合AspectJ使用 @Transactional 9.6. 编程式事务管理 9.6.1. 使用 TransactionTemplate 9.6.2. 使用 PlatformTransactionManager 9.7. 选择编程式事务管理还是声明式事务管理 9.8. 与特定应用服务器集成 9.8.1. BEA WebLogic 9.8.2. IBM WebSphere 9.9. 公共问题的解决方案 9.9.1. 对一个特定的 DataSource 使用错误的事务管理器 9.10. 更多的资源 10. DAO支持 10.1. 简介 10.2. 一致的异常层次 10.3. 一致的DAO支持抽象类 11. 使用JDBC进行数据访问 11.1. 简介 11.1.1. Spring JDBC包结构 11.2. 利用JDBC核心类实现JDBC的基本操作和错误处理 11.2.1. JdbcTemplate类 11.2.2. NamedParameterJdbcTemplate类 11.2.3. SimpleJdbcTemplate类 11.2.4. DataSource接口 11.2.5. SQLExceptionTranslator接口 11.2.6. 执行SQL语句 11.2.7. 执行查询 11.2.8. 更新数据库 11.3. 控制数据库连接 11.3.1. DataSourceUtils类 11.3.2. SmartDataSource接口 11.3.3. AbstractDataSource类 11.3.4. SingleConnectionDataSource类 11.3.5. DriverManagerDataSource类 11.3.6. TransactionAwareDataSourceProxy类 11.3.7. DataSourceTransactionManager类 11.4. 用Java对象来表达JDBC操作 11.4.1. SqlQuery类 11.4.2. MappingSqlQuery类 11.4.3. SqlUpdate类 11.4.4. StoredProcedure类 11.4.5. SqlFunction类 12. 使用ORM工具进行数据访问 12.1. 简介 12.2. Hibernate 12.2.1. 资源管理 12.2.2. 在Spring的application context中创建 SessionFactory 12.2.3. HibernateTemplate 12.2.4. 不使用回调的基于Spring的DAO实现 12.2.5. 基于Hibernate3的原生API实现DAO 12.2.6. 编程式的事务划分 12.2.7. 声明式的事务划分 12.2.8. 事务管理策略 12.2.9. 容器资源 vs 本地资源 12.2.10. 在应用服务器中使用Hibernate的注意点 12.3. JDO 12.3.1. 建立PersistenceManagerFactory 12.3.2. JdoTemplate和JdoDaoSupport 12.3.3. 基于原生的JDO API实现DAO 12.3.4. 事务管理 12.3.5. JdoDialect 12.4. Oracle TopLink 12.4.1. SessionFactory 抽象层 12.4.2. TopLinkTemplate 和 TopLinkDaoSupport 12.4.3. 基于原生的TopLink API的DAO实现 12.4.4. 事务管理 12.5. iBATIS SQL Maps 12.5.1. iBATIS 1.x和2.x的概览与区别 12.5.2. iBATIS SQL Maps 1.x 12.5.2.1. 创建SqlMap 12.5.2.2. 使用 SqlMapTemplate 和 SqlMapDaoSupport 12.5.3. iBATIS SQL Maps 2.x 12.5.3.1. 创建SqlMapClient 12.5.3.2. 使用 SqlMapClientTemplate 和 SqlMapClientDaoSupport 12.5.3.3. 基于原生的iBATIS API的DAO实现 12.6. JPA 12.6.1. 在Spring环境中建立JPA 12.6.1.1. LocalEntityManagerFactoryBean 12.6.1.2. LocalContainerEntityManagerFactoryBean 12.6.1.3. 处理多个持久化单元 12.6.2. JpaTemplate 和 JpaDaoSupport 12.6.3. 基于原生的JPA实现DAO 12.6.4. 异常转化 12.6.5. 事务管理 12.6.6. JpaDialect III. Web 13. Web框架 13.1. 介绍 13.1.1. 与其他web框架的集成 13.1.2. Spring Web MVC框架的特点 13.2. DispatcherServlet 13.3. 控制器 13.3.1. AbstractController 和 WebContentGenerator 13.3.2. 其它的简单控制器 13.3.3. MultiActionController 13.3.4. 命令控制器 13.4. 处理器映射(handler mapping) 13.4.1. BeanNameUrlHandlerMapping 13.4.2. SimpleUrlHandlerMapping 13.4.3. 拦截器(HandlerInterceptor) 13.5. 视图与视图解析 13.5.1. 视图解析器 13.5.2. 视图解析链 13.5.3. 重定向(Rediret)到另一个视图 13.5.3.1. RedirectView 13.5.3.2. redirect:前缀 13.5.3.3. forward:前缀 13.6. 本地化解析器 13.6.1. AcceptHeaderLocaleResolver 13.6.2. CookieLocaleResolver 13.6.3. SessionLocaleResolver 13.6.4. LocaleChangeInterceptor 13.7. 使用主题 13.7.1. 简介 13.7.2. 如何定义主题 13.7.3. 主题解析器 13.8. Spring对分段文件上传(multipart file upload)的支持 13.8.1. 介绍 13.8.2. 使用MultipartResolver 13.8.3. 在表单中处理分段文件上传 13.9. 使用Spring的表单标签库 13.9.1. 配置标签库 13.9.2. form标签 13.9.3. input标签 13.9.4. checkbox标签 13.9.5. radiobutton标签 13.9.6. password标签 13.9.7. select标签 13.9.8. option标签 13.9.9. options标签 13.9.10. textarea标签 13.9.11. hidden标签 13.9.12. errors标签 13.10. 处理异常 13.11. 惯例优先原则(convention over configuration) 13.11.1. 对控制器的支持: ControllerClassNameHandlerMapping 13.11.2. 对模型的支持:ModelMap (ModelAndView) 13.11.3. 对视图的支持: RequestToViewNameTranslator 13.12. 其它资源 14. 集成视图技术 14.1. 简介 14.2. JSP和JSTL 14.2.1. 视图解析器 14.2.2. 'Plain-old' JSPs versus JSTL 'Plain-old' JSP与JSTL 14.2.3. 帮助简化开发的额外的标签 14.3. Tiles 14.3.1. 需要的资源 14.3.2. 如何集成Tiles 14.3.2.1. InternalResourceViewResolver 14.3.2.2. ResourceBundleViewResolver 14.4. Velocity和FreeMarker 14.4.1. 需要的资源 14.4.2. Context 配置 14.4.3. 创建模板 14.4.4. 高级配置 14.4.4.1. velocity.properties 14.4.4.2. FreeMarker 14.4.5. 绑定支持和表单处理 14.4.5.1. 用于绑定的宏 14.4.5.2. 简单绑定 14.4.5.3. 表单输入生成宏 14.4.5.4. 重载HTML转码行为并使你的标签符合XHTML 14.5. XSLT 14.5.1. 写在段首 14.5.1.1. Bean 定义 14.5.1.2. 标准MVC控制器代码 14.5.1.3. 把模型数据转化为XML 14.5.1.4. 定义视图属性 14.5.1.5. 文档转换 14.5.2. 小结 14.6. 文档视图(PDF/Excel) 14.6.1. 简介 14.6.2. 配置和安装 14.6.2.1. 文档视图定义 14.6.2.2. Controller 代码 14.6.2.3. Excel视图子类 14.6.2.4. PDF视图子类 14.7. JasperReports 14.7.1. 依赖的资源 14.7.2. 配置 14.7.2.1. 配置ViewResolver 14.7.2.2. 配置View 14.7.2.3. 关于报表文件 14.7.2.4. 使用 JasperReportsMultiFormatView 14.7.3. 构造ModelAndView 14.7.4. 使用子报表 14.7.4.1. 配置子报表文件 14.7.4.2. 配置子报表数据源 14.7.5. 配置Exporter的参数 15. 集成其它Web框架 15.1. 简介 15.2. 通用配置 15.3. JavaServer Faces 15.3.1. DelegatingVariableResolver 15.3.2. FacesContextUtils 15.4. Struts 15.4.1. ContextLoaderPlugin 15.4.1.1. DelegatingRequestProcessor 15.4.1.2. DelegatingActionProxy 15.4.2. ActionSupport 类 15.5. Tapestry 15.5.1. 注入 Spring 托管的 beans 15.5.1.1. 将 Spring Beans 注入到 Tapestry 页面中 15.5.1.2. 组件定义文件 15.5.1.3. 添加抽象访问方法 15.5.1.4. 将 Spring Beans 注入到 Tapestry 页面中 - Tapestry 4.0+ 风格 15.6. WebWork 15.7. 更多资源 16. Portlet MVC框架 16.1. 介绍 16.1.1. 控制器 - MVC中的C 16.1.2. 视图 - MVC中的V 16.1.3. Web作用范围的Bean 16.2. DispatcherPortlet 16.3. ViewRendererServlet 16.4. 控制器 16.4.1. AbstractController和PortletContentGenerator 16.4.2. 其它简单的控制器 16.4.3. Command控制器 16.4.4. PortletWrappingController 16.5. 处理器映射 16.5.1. PortletModeHandlerMapping 16.5.2. ParameterHandlerMapping 16.5.3. PortletModeParameterHandlerMapping 16.5.4. 增加 HandlerInterceptor 16.5.5. HandlerInterceptorAdapter 16.5.6. ParameterMappingInterceptor 16.6. 视图和它们的解析 16.7. Multipart文件上传支持 16.7.1. 使用PortletMultipartResolver 16.7.2. 处理表单里的文件上传 16.8. 异常处理 16.9. Portlet应用的部署 IV. 整合 17. 使用Spring进行远程访问与Web服务 17.1. 简介 17.2. 使用RMI暴露服务 17.2.1. 使用 RmiServiceExporter 暴露服务 17.2.2. 在客户端链接服务 17.3. 使用Hessian或者Burlap通过HTTP远程调用服务 17.3.1. 为Hessian配置DispatcherServlet 17.3.2. 使用HessianServiceExporter暴露你的bean 17.3.3. 客户端连接服务 17.3.4. 使用Burlap 17.3.5. 对通过Hessian或Burlap暴露的服务使用HTTP基础认证 17.4. 使用HTTP调用器暴露服务 17.4.1. 暴露服务对象 17.4.2. 在客户端连接服务 17.5. Web服务 17.5.1. 使用JAXI-RPC暴露服务 17.5.2. 访问Web服务 17.5.3. 注册bean映射 17.5.4. 注册自己的处理方法 17.5.5. 使用XFire来暴露Web服务 17.6. 对远程接口不提供自动探测 17.7. 在选择这些技术时的一些考虑 18. Enterprise Java Bean(EJB)集成 18.1. 简介 18.2. 访问EJB 18.2.1. 概念 18.2.2. 访问本地的无状态Session Bean(SLSB) 18.2.3. 访问远程SLSB 18.3. 使用Spring提供的辅助类实现EJB组件 19. JMS 19.1. 简介 19.2. 使用Spring JMS 19.2.1. JmsTemplate 19.2.2. 连接工厂 19.2.3. (消息)目的地管理 19.2.4. 消息侦听容器 19.2.4.1. SimpleMessageListenerContainer 19.2.4.2. DefaultMessageListenerContainer 19.2.4.3. ServerSessionMessageListenerContainer 19.2.5. 事务管理 19.3. 发送一条消息 19.3.1. 使用消息转换器 19.3.2. SessionCallback 和ProducerCallback 19.4. 接收消息 19.4.1. 同步接收 19.4.2. 异步接收 - 消息驱动的POJOs 19.4.3. SessionAwareMessageListener 接口 19.4.4. MessageListenerAdapter 19.4.5. 事务中的多方参与 20. JMX 20.1. 介绍 20.2. 输出bean到JMX 20.2.1. 创建一个MBeanServer 20.2.2. 复用现有的MBeanServer 20.2.3. MBean的惰性初始化 20.2.4. MBean的自动注册 20.2.5. 控制注册行为 20.3. 控制bean的管理接口 20.3.1. MBeanInfoAssembler 接口 20.3.2. 使用源码级元数据 20.3.3. 使用JDK 5.0注解 20.3.4. 源代码级的元数据类型 20.3.5. 接口AutodetectCapableMBeanInfoAssembler 20.3.6. 用Java接口定义管理接口 20.3.7. 使用MethodNameBasedMBeanInfoAssembler 20.4. 控制bean的 ObjectName 20.4.1. 从Properties中读取ObjectName 20.4.2. 使用 MetadataNamingStrategy 20.5. JSR-160连接器 20.5.1. 服务器端连接器 20.5.2. 客户端连接器 20.5.3. 基于Burlap/Hessian/SOAP的JMX 20.6. 通过代理访问MBeans 20.7. 通知 20.7.1. 为通知注册监听器 20.7.2. 发布通知 20.8. 更多资源 21. JCA CCI 21.1. 介绍 21.2. 配置CCI 21.2.1. 连接器配置 21.2.2. 在Spring中配置ConnectionFactory 21.2.3. 配置CCI连接 21.2.4. 使用一个 CCI 单连接 21.3. 使用Spring的 CCI访问支持 21.3.1. 记录转换 21.3.2. CciTemplate 类 21.3.3. DAO支持 21.3.4. 自动输出记录生成 21.3.5. 总结 21.3.6. 直接使用一个 CCI Connection 接口和Interaction接口 21.3.7. CciTemplate 使用示例 21.4. 建模CCI访问为操作对象 21.4.1. MappingRecordOperation 21.4.2. MappingCommAreaOperation 21.4.3. 自动输出记录生成 21.4.4. 总结 21.4.5. MappingRecordOperation 使用示例 21.4.6. MappingCommAreaOperation 使用示例 21.5. 事务 22. Spring邮件抽象层 22.1. 简介 22.2. Spring邮件抽象结构 22.3. 使用Spring邮件抽象 22.3.1. 可插拔的MailSender实现 22.4. 使用 JavaMail MimeMessageHelper 22.4.1. 创建一条简单的MimeMessage,并且发送出去 22.4.2. 发送附件和嵌入式资源(inline resources) 23. Spring中的定时调度(Scheduling)和线程池(Thread Pooling) 23.1. 简介 23.2. 使用OpenSymphony Quartz 调度器 23.2.1. 使用JobDetailBean 23.2.2. 使用 MethodInvokingJobDetailFactoryBean 23.2.3. 使用triggers和SchedulerFactoryBean来包装任务 23.3. 使用JDK Timer支持类 23.3.1. 创建定制的timers 23.3.2. 使用 MethodInvokingTimerTaskFactoryBean类 23.3.3. 打包:使用TimerFactoryBean来设置任务 23.4. SpringTaskExecutor抽象 23.4.1. TaskExecutor接口 23.4.2. 何时使用TaskExecutor接口 23.4.3. TaskExecutor类型 23.4.4. 使用TaskExecutor接口 24. 动态语言支持 24.1. 介绍 24.2. 第一个例子 24.3. 定义动态语言支持的bean 24.3.1. 公共概念 24.3.1.1. <lang:language/> 元素 24.3.1.2. Refreshable bean 24.3.1.3. 内置动态语言源文件 24.3.1.4. 理解dynamic-language-backed bean context的构造器注入 24.3.2. JRuby beans 24.3.3. Groovy beans 24.3.4. BeanShell beans 24.4. 场景 24.4.1. Spring MVC控制器脚本化 24.4.2. Validator脚本化 24.5. 更多的资源 25. 注解和源代码级的元数据支持 25.1. 简介 25.2. Spring的元数据支持 25.3. 注解 25.3.1. @Required 25.3.2. Spring中的其它@Annotations 25.4. 集成Jakarta Commons Attributes 25.5. 元数据和Spring AOP自动代理 25.5.1. 基本原理 25.5.2. 声明式事务管理 25.5.3. 缓冲 25.5.4. 自定义元数据 25.6. 使用属性来减少MVC web层配置 25.7. 元数据属性的其它用法 25.8. 增加对额外元数据API的支持 A. XML Schema-based configuration A.1. Introduction A.2. XML Schema-based configuration A.2.1. Referencing the schemas A.2.2. The util schema A.2.2.1. <util:constant/> A.2.2.2. <util:property-path/> A.2.2.3. <util:properties/> A.2.2.4. <util:list/> A.2.2.5. <util:map/> A.2.2.6. <util:set/> A.2.3. The jee schema A.2.3.1. <jee:jndi-lookup/> (simple) A.2.3.2. <jee:jndi-lookup/> (with single JNDI environment setting) A.2.3.3. <jee:jndi-lookup/> (with multiple JNDI environment settings) A.2.3.4. <jee:jndi-lookup/> (complex) A.2.3.5. <jee:local-slsb/> (simple) A.2.3.6. <jee:local-slsb/> (complex) A.2.3.7. <jee:remote-slsb/> A.2.4. The lang schema A.2.5. The tx (transaction) schema A.2.6. The aop schema A.2.7. The tool schema A.2.8. The beans schema A.3. Setting up your IDE A.3.1. Setting up Eclipse A.3.2. Setting up IntelliJ IDEA A.3.3. Integration issues A.3.3.1. XML parsing errors in the Resin v.3 application server B. Extensible XML authoring B.1. Introduction B.2. Authoring the schema B.3. Coding a NamespaceHandler B.4. Coding a BeanDefinitionParser B.5. Registering the handler and the schema B.5.1. META-INF/spring.handlers B.5.2. META-INF/spring.schemas C. spring-beans-2.0.dtd D. spring.tld D.1. Introduction D.2. The bind tag D.3. The escapeBody tag D.4. The hasBindErrors tag D.5. The htmlEscape tag D.6. The message tag D.7. The nestedPath tag D.8. The theme tag D.9. The transform tag E. spring-form.tld E.1. Introduction E.2. The checkbox tag E.3. The errors tag E.4. The form tag E.5. The hidden tag E.6. The input tag E.7. The label tag E.8. The option tag E.9. The options tag E.10. The password tag E.11. The radiobutton tag E.12. The select tag E.13. The textarea tag F. Spring 2.0 开发手册中文化项目 F.1. 声明 F.2. 致谢 F.3. 参与人员及任务分配 F.4. Spring 2.0 正式版开发手册翻译说明 F.5. 项目历程 F.5.1. Spring 2.0 RC2 开发手册翻译项目 F.5.2. Spring 2.0 正式版开发手册翻译项目

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值