[Spring Framework Documentation]
https://docs.spring.io/spring/docs/5.1.4.RELEASE/spring-framework-reference/index.html
Version 5.1.4.RELEASE
目录
1.事务管理
1.1 Spring Framework的事务支持模型的优点
1.2 理解Spring Framework事务抽象
1.3 资源与事务同步
1.4 声明式事务管理
1.5 程序化事务管理
1.6 在程序化和声明式事务管理之间进行选择
1.7 事务约束事件
1.8 特定于应用程序服务器的集
1.9 解决常见问题
1.10 更多资源
- DAO支持
3.使用JDBC进行数据访问
4.对象关系映射(ORM)数据访问
5.使用Object-XML Mappers编组XML
6.附录
1. Transaction Management
1.1. Advantages of the Spring Framework’s Transaction Support Model
1.2. Understanding the Spring Framework Transaction Abstraction
1.3. Synchronizing Resources with Transactions
1.4. Declarative transaction management
1.5. Programmatic Transaction Management
1.6. Choosing Between Programmatic and Declarative Transaction Management
1.7. Transaction-bound Events
1.8. Application server-specific integration
1.9. Solutions to Common Problems
1.10. Further Resources
2. DAO Support
3. Data Access with JDBC
4. Object Relational Mapping (ORM) Data Access
5. Marshalling XML by Using Object-XML Mappers
6. Appendix
数据访问 Data Access
这部分参考文档涉及数据访问以及数据访问层与业务或服务层之间的交互。
Spring详细介绍了Spring的全面事务管理支持,然后详细介绍了Spring Framework集成的各种数据访问框架和技术。
This part of the reference documentation is concerned with data access and the interaction between the data access layer and the business or service layer.
Spring’s comprehensive transaction management support is covered in some detail, followed by thorough coverage of the various data access frameworks and technologies with which the Spring Framework integrates.
1.事务管理
全面的事务支持是使用Spring Framework的最有说服力的理由之一。 Spring Framework为事务管理提供了一致的抽象,具有以下优势:
Comprehensive transaction support is among the most compelling reasons to use the Spring Framework. The Spring Framework provides a consistent abstraction for transaction management that delivers the following benefits:
跨不同事务API的一致编程模型,例如Java Transaction API(JTA),JDBC,Hibernate和Java Persistence API(JPA)。
A consistent programming model across different transaction APIs, such as Java Transaction API (JTA), JDBC, Hibernate, and the Java Persistence API (JPA).
支持声明式事务管理。
Support for declarative transaction management.
1.4更简单的编程事务管理API,对比复杂事务API(如JTA),更简单。
A simpler API for programmatic transaction management than complex transaction APIs, such as JTA.
1.5与Spring的数据访问抽象集成。
Excellent integration with Spring’s data access abstractions.
以下部分描述了Spring Framework的事务功能和技术:
- Spring Framework的事务支持模型的优点描述了为什么要使用Spring Framework的事务抽象而不是EJB容器管理事务(CMT)或选择通过专有API(如Hibernate)来驱动本地事务。
Advantages of the Spring Framework’s transaction support model describes why you would use the Spring Framework’s transaction abstraction instead of EJB Container-Managed Transactions (CMT) or choosing to drive local transactions through a proprietary API, such as Hibernate.
1.1
- 理解Spring Framework事务抽象概述了核心类,并描述了如何从各种源配置和获取DataSource实例。
Understanding the Spring Framework transaction abstraction outlines the core classes and describes how to configure and obtain DataSource instances from a variety of sources.
1.2
使用事务同步资源,描述了应用程序代码如何确保正确创建,重用和清理资源。
Synchronizing resources with transactions describes how the application code ensures that resources are created, reused, and cleaned up properly.
1.3声明式事务管理,描述了对声明式事务管理的支持。
Declarative transaction management describes support for declarative transaction management.
1.4程序化事务管理,包括对程序化(即明确编码)事务管理的支持。
Programmatic transaction management covers support for programmatic (that is, explicitly coded) transaction management.
1.5事务绑定事件,描述了如何在事务中使用应用程序事件。
Transaction bound event describes how you could use application events within a transaction.
1.7
(本章还包括对最佳实践,应用程序服务器集成以及常见问题解决方案的讨论。)
(The chapter also includes discussions of best practices, application server integration[1.8], and solutions to common problems[1.9].)
1.8,1.9.
1.1 Spring Framework的事务支持模型的优点
传统上,Java EE开发人员有两种交易管理选择:全局或本地交易,这两种交易都有很大的局限性。 在接下来的两节中将对全局和本地事务管理进行审查,然后讨论Spring Framework的事务管理支持如何解决全局和本地事务模型的局限性。Advantages of the Spring Framework’s Transaction Support Model Traditionally, Java EE developers have had two choices for transaction management: global or local transactions, both of which have profound limitations. Global and local transaction management is reviewed in the next two sections, followed by a discussion of how the Spring Framework’s transaction management support addresses the limitations of the global and local transaction models.
1.1.1全局事务 Global Transactions
全局事务允许您使用多个事务资源,通常是关系数据库和消息队列。应用程序服务器通过JTA管理全局事务,这是一个繁琐的API(部分原因是它的异常模型)。此外,JTA UserTransaction通常需要从JNDI获取,这意味着您还需要使用JNDI才能使用JTA。全局事务的使用限制了应用程序代码的任何潜在重用,因为JTA通常仅在应用程序服务器环境中可用。
以前,使用全局事务的首选方法是通过EJB CMT(容器管理事务)。 CMT是一种声明式事务管理(与程序化事务管理不同)。 EJB CMT消除了与事务相关的JNDI查找的需要,尽管使用EJB本身需要使用JNDI。它消除了编写Java代码以控制事务的大部分但不是全部的需要。重要的缺点是CMT与JTA和应用服务器环境相关联。此外,仅当选择在EJB中实现业务逻辑(或至少在事务EJB外观之后)时,它才可用。一般来说,EJB的负面影响是如此之大,以至于这不是一个有吸引力的主张,特别是面对声明式事务管理的令人信服的替代方案。
Global transactions let you work with multiple transactional resources, typically relational databases and message queues. The application server manages global transactions through the JTA, which is a cumbersome API (partly due to its exception model). Furthermore, a JTA UserTransaction normally needs to be sourced from JNDI, meaning that you also need to use JNDI in order to use JTA. The use of global transactions limits any potential reuse of application code, as JTA is normally only available in an application server environment.
Previously, the preferred way to use global transactions was through EJB CMT (Container Managed Transaction). CMT is a form of declarative transaction management (as distinguished from programmatic transaction management). EJB CMT removes the need for transaction-related JNDI lookups, although the use of EJB itself necessitates the use of JNDI. It removes most but not all of the need to write Java code to control transactions. The significant downside is that CMT is tied to JTA and an application server environment. Also, it is only available if one chooses to implement business logic in EJBs (or at least behind a transactional EJB facade). The negatives of EJB in general are so great that this is not an attractive proposition, especially in the face of compelling alternatives for declarative transaction management.
1.1.2 本地交易 Local Transactions
本地事务是特定于资源的,例如与JDBC连接关联的事务。 本地事务可能更容易使用,但具有明显的缺点:它们无法跨多个事务资源工作。 例如,使用JDBC连接管理事务的代码无法在全局JTA事务中运行。 由于应用程序服务器不参与事务管理,因此无法确保跨多个资源的正确性。 (值得注意的是,大多数应用程序使用单个事务资源。)另一个缺点是本地事务对编程模型是侵入性的。
Local transactions are resource-specific, such as a transaction associated with a JDBC connection. Local transactions may be easier to use but have a significant disadvantage: They cannot work across multiple transactional resources. For example, code that manages transactions by using a JDBC connection cannot run within a global JTA transaction. Because the application server is not involved in transaction management, it cannot help ensure correctness across multiple resources. (It is worth noting that most applications use a single transaction resource.) Another downside is that local transactions are invasive to the programming model.
1.1.3 Spring Framework的一致性编程模型
Spring解决了全局和本地事务的缺点。 它允许应用程序开发人员在任何环境中使用一致的编程模型 您只需编写一次代码,就可以从不同环境中的不同事务管理策略中受益。 Spring Framework提供了声明式和编程式事务管理。 大多数用户更喜欢声明式事务管理,我们建议在大多数情况下使用。
通过编程式事务管理,开发人员可以使用Spring Framework事务抽象,它可以在任何底层事务基础结构上运行。 使用首选的声明性模型,开发人员通常很少编写或不编写与事务管理相关的代码,因此不依赖于Spring Framework事务API或任何其他事务API
。Spring resolves the disadvantages of global and local transactions. It lets application developers use a consistent programming model in any environment. You write your code once, and it can benefit from different transaction management strategies in different environments. The Spring Framework provides both declarative and programmatic transaction management. Most users prefer declarative transaction management, which we recommend in most cases. With programmatic transaction management, developers work with the Spring Framework transaction abstraction, which can run over any underlying transaction infrastructure. With the preferred declarative model, developers typically write little or no code related to transaction management and, hence, do not depend on the Spring Framework transaction API or any other transaction API.
您是否需要应用程序服务器进行事务管理?
Spring Framework的事务管理支持改变了关于企业Java应用程序何时需要应用程序服务器的传统规则。Do you need an application server for transaction management? The Spring Framework’s transaction management support changes traditional rules as to when an enterprise Java application requires an application server.
特别是,您不需要纯粹用于通过EJB进行声明式事务的应用程序服务器。实际上,即使您的应用程序服务器具有强大的JTA功能,您也可以决定Spring Framework的声明性事务提供比EJB CMT更强大的功能和更高效的编程模型。*In particular*, you do not need an application server purely for declarative transactions through EJBs. In fact, even if your application server has powerful JTA capabilities, you may decide that the Spring Framework’s declarative transactions offer more power and a more productive programming model than EJB CMT.
通常,只有当您的应用程序需要处理跨多个资源的事务时,才需要应用程序服务器的JTA功能,这对许多应用程序来说并不是必需的。许多高端应用程序使用单个高度可伸缩的数据库(例如Oracle RAC)。独立的事务管理器(例如Atomikos Transactions和JOTM)是其他选项。当然,您可能需要其他应用程序服务器功能,例如Java消息服务(JMS)和Java EE连接器体系结构(JCA)。Typically, you need an application server’s JTA capability only if your application needs to handle transactions across multiple resources, which is not a requirement for many applications. Many high-end applications use a single, highly scalable database (such as Oracle RAC) instead. Stand-alone transaction managers (such as Atomikos Transactions and JOTM) are other options. Of course, you may need other application server capabilities, such as Java Message Service (JMS) and Java EE Connector Architecture (JCA).
Spring Framework使您可以选择何时将应用程序扩展到完全加载的应用程序服务器。使用EJB CMT或JTA的唯一替代方法是使用本地事务(例如JDBC连接上的代码)编写代码,并且如果您需要在全局容器管理的事务中运行代码,则会面临大量的返工。使用Spring Framework,只需要更改配置文件中的一些bean定义(而不是代码)。The Spring Framework gives you the choice of when to scale your application to a fully loaded application server. Gone are the days when the only alternative to using EJB CMT or JTA was to write code with local transactions (such as those on JDBC connections) and face a hefty rework if you need that code to run within global, container-managed transactions. With the Spring Framework, only some of the bean definitions in your configuration file need to change (rather than your code).
1.2 理解Spring Framework事务抽象
Understanding the Spring Framework Transaction Abstraction
Spring事务抽象的关键是事务策略的概念。 事务策略由org.springframework.transaction.PlatformTransactionManager接口定义,如下所示:
The key to the Spring transaction abstraction is the notion of a transaction strategy. A transaction strategy is defined by the org.springframework.transaction.PlatformTransactionManager interface, which the following listing shows:
public interface PlatformTransactionManager {
TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException;
void commit(TransactionStatus status) throws TransactionException;
void rollback(TransactionStatus status) throws TransactionException;
}
这主要是服务提供者接口(SPI),尽管您可以从应用程序代码中以编程方式使用它。 因为PlatformTransactionManager是一个接口,所以可以根据需要轻松地模拟或存根。 它与查找策略无关,例如JNDI。 PlatformTransactionManager实现的定义与Spring Framework IoC容器中的任何其他对象(或bean)相同。 仅使用此优势使Spring Framework事务成为一种有价值的抽象,即使您使用JTA也是如此。 与直接使用JTA相比,您可以更轻松地测试事务代码。
This is primarily a service provider interface (SPI), although you can use it programmatically from your application code. Because PlatformTransactionManager is an interface, it can be easily mocked or stubbed as necessary. It is not tied to a lookup strategy, such as JNDI. PlatformTransactionManager implementations are defined like any other object (or bean) in the Spring Framework IoC container. This benefit alone makes Spring Framework transactions a worthwhile abstraction, even when you work with JTA. You can test transactional code much more easily than if it used JTA directly.
同样,为了与Spring的理念保持一致,可以取消选中任何PlatformTransactionManager接口的方法抛出的TransactionException(即,它扩展了java.lang.RuntimeException类)。 交易基础设施故障几乎总是致命的。 在极少数情况下,应用程序代码实际上可以从事务失败中恢复,应用程序开发人员仍然可以选择捕获并处理TransactionException。 重点是开发人员不会被迫这样做。
Again, in keeping with Spring’s philosophy, the TransactionException that can be thrown by any of the PlatformTransactionManager interface’s methods is unchecked (that is, it extends the java.lang.RuntimeException class). Transaction infrastructure failures are almost invariably fatal. In rare cases where application code can actually recover from a transaction failure, the application developer can still choose to catch and handle TransactionException. The salient point is that developers are not forced to do so.
getTransaction(..)方法返回TransactionStatus对象,具体取决于TransactionDefinition参数。 如果当前调用堆栈中存在匹配的事务,则返回的TransactionStatus可能表示新事务或可以表示现有事务。 后一种情况的含义是,与Java EE事务上下文一样,TransactionStatus与执行线程相关联。
The getTransaction(..) method returns a TransactionStatus object, depending on a TransactionDefinition parameter. The returned TransactionStatus might represent a new transaction or can represent an existing transaction, if a matching transaction exists in the current call stack. The implication in this latter case is that, as with Java EE transaction contexts, a TransactionStatus is associated with a thread of execution.
TransactionDefinition接口指定:
The TransactionDefinition interface specifies:
传播(Propagation):通常,在事务范围内执行的所有代码都在该事务中运行。但是,如果在事务上下文已存在时执行事务方法,则可以指定行为。例如,代码可以继续在现有事务中运行(常见情况),或者可以暂停现有事务并创建新事务。 Spring提供了EJB CMT中熟悉的所有事务传播选项。要阅读有关Spring中事务传播的语义,请参阅事务传播。
隔离(Isolation):此事务与其他事务的工作隔离的程度。例如,此事务是否可以看到来自其他事务的未提交的写入?
超时(Timeout):此事务在超时之前运行多长时间并由底层事务基础结构自动回滚。
只读状态(Read-only):您可以在代码读取时使用只读事务,但不能修改数据。在某些情况下,只读事务可能是一种有用的优化,例如当您使用Hibernate时。
Propagation: Typically, all code executed within a transaction scope runs in that transaction. However, you can specify the behavior if a transactional method is executed when a transaction context already exists. For example, code can continue running in the existing transaction (the common case), or the existing transaction can be suspended and a new transaction created. Spring offers all of the transaction propagation options familiar from EJB CMT. To read about the semantics of transaction propagation in Spring, see Transaction Propagation.
Isolation: The degree to which this transaction is isolated from the work of other transactions. For example, can this transaction see uncommitted writes from other transactions?
Timeout: How long this transaction runs before timing out and being automatically rolled back by the underlying transaction infrastructure.
Read-only status: You can use a read-only transaction when your code reads but does not modify data. Read-only transactions can be a useful optimization in some cases, such as when you use Hibernate.
这些设置反映了标准的事务概念。 如有必要,请参阅讨论事务隔离级别和其他核心事务概念的资源。 理解这些概念对于使用Spring Framework或任何事务管理解决方案至关重要。
These settings reflect standard transactional concepts. If necessary, refer to resources that discuss transaction isolation levels and other core transaction concepts. Understanding these concepts is essential to using the Spring Framework or any transaction management solution.
TransactionStatus接口为事务代码提供了一种控制事务执行和查询事务状态的简单方法。 这些概念应该是熟悉的,因为它们对于所有事务API都是通用的。 以下清单显示了TransactionStatus接口:
The TransactionStatus interface provides a simple way for transactional code to control transaction execution and query transaction status. The concepts should be familiar, as they are common to all transaction APIs. The following listing shows the TransactionStatus interface:
public interface TransactionStatus extends SavepointManager {
boolean isNewTransaction();
boolean hasSavepoint();
void setRollbackOnly();
boolean isRollbackOnly();
void flush();
boolean isCompleted();
}
无论您是在Spring中选择声明式还是程序化事务管理,定义正确的PlatformTransactionManager实现都是绝对必要的。 您通常通过依赖注入来定义此实现。
Regardless of whether you opt for declarative or programmatic transaction management in Spring, defining the correct PlatformTransactionManager implementation is absolutely essential. You typically define this implementation through dependency injection.
PlatformTransactionManager实现通常需要了解它们工作的环境:JDBC,JTA,Hibernate等。 以下示例显示如何定义本地PlatformTransactionManager实现(在本例中,使用纯JDBC)。
PlatformTransactionManager implementations normally require knowledge of the environment in which they work: JDBC, JTA, Hibernate, and so on. The following examples show how you can define a local PlatformTransactionManager implementation (in this case, with plain JDBC.)
您可以通过创建类似于以下内容的bean来定义JDBC DataSource:
You can define a JDBC DataSource by creating a bean similar to the following:
<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>
然后,相关的PlatformTransactionManager bean定义具有对DataSource定义的引用。 它应该类似于以下示例:
The related PlatformTransactionManager bean definition then has a reference to the DataSource definition. It should resemble the following example:
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
如果在Java EE容器中使用JTA,则使用通过JNDI获得的容器DataSource以及Spring的JtaTransactionManager。 以下示例显示了JTA和JNDI查找版本的外观:
If you use JTA in a Java EE container, then you use a container DataSource, obtained through JNDI, in conjunction with Spring’s JtaTransactionManager. The following example shows what the JTA and JNDI lookup version would look like:
<?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:jee="http://www.springframework.org/schema/jee"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/jee
http://www.springframework.org/schema/jee/spring-jee.xsd">
<jee:jndi-lookup id="dataSource" jndi-name="jdbc/jpetstore"/>
<bean id="txManager" class="org.springframework.transaction.jta.JtaTransactionManager" />
<!-- other <bean/> definitions here -->
</beans>
JtaTransactionManager不需要知道DataSource(或任何其他特定资源),因为它使用容器的全局事务管理基础结构。
The JtaTransactionManager does not need to know about the DataSource (or any other specific resources) because it uses the container’s global transaction management infrastructure.
dataSource bean的前面定义使用jee名称空间中的<jndi-lookup />标记。 有关更多信息,请参阅JEE架构。The preceding definition of the dataSource bean uses the <jndi-lookup/> tag from the jee namespace. For more information see The JEE Schema.
您还可以轻松使用Hibernate本地事务,如以下示例所示。 在这种情况下,您需要定义一个Hibernate LocalSessionFactoryBean,您的应用程序代码可以使用它来获取Hibernate Session实例。
You can also use easily Hibernate local transactions, as shown in the following examples. In this case, you need to define a Hibernate LocalSessionFactoryBean, which your application code can use to obtain Hibernate Session instances.
DataSource bean定义类似于前面显示的本地JDBC示例,因此未在以下示例中显示。
The DataSource bean definition is similar to the local JDBC example shown previously and, thus, is not shown in the following example.
如果DataSource(由任何非JTA事务管理器使用)通过JNDI查找并由Java EE容器管理,则它应该是非事务性的,因为Spring Framework(而不是Java EE容器)管理事务。*If the DataSource (used by any non-JTA transaction manager) is looked up through JNDI and managed by a Java EE container, it should be non-transactional, because the Spring Framework (rather than the Java EE container) manages the transactions.*
在这种情况下,txManager bean是HibernateTransactionManager类型。 与DataSourceTransactionManager需要对DataSource的引用一样,HibernateTransactionManager需要对SessionFactory的引用。 以下示例声明了sessionFactory和txManager bean:
The txManager bean in this case is of the HibernateTransactionManager type. In the same way as the DataSourceTransactionManager needs a reference to the DataSource, the HibernateTransactionManager needs a reference to the SessionFactory. The following example declares sessionFactory and txManager beans:
<bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="mappingResources">
<list>
<value>org/springframework/samples/petclinic/hibernate/petclinic.hbm.xml</value>
</list>
</property>
<property name="hibernateProperties">
<value>
hibernate.dialect=${hibernate.dialect}
</value>
</property>
</bean>
<bean id="txManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
如果使用Hibernate和Java EE容器管理的JTA事务,则应使用与之前的JDBC JTA示例相同的JtaTransactionManager,如以下示例所示:
If you use Hibernate and Java EE container-managed JTA transactions, you should use the same JtaTransactionManager as in the previous JTA example for JDBC, as the following example shows:
<bean id="txManager" class="org.springframework.transaction.jta.JtaTransactionManager"/>
【如果使用JTA,则无论使用何种数据访问技术,无论是JDBC,Hibernate JPA还是任何其他支持的技术,您的事务管理器定义应该看起来都一样。 这是因为JTA事务是全局事务,可以登记任何事务资源。】
[If you use JTA, your transaction manager definition should look the same, regardless of what data access technology you use, be it JDBC, Hibernate JPA, or any other supported technology. This is due to the fact that JTA transactions are global transactions, which can enlist any transactional resource.]
在所有这些情况下,应用程序代码不需要更改。 您可以仅通过更改配置来更改事务的管理方式,即使该更改意味着从本地事务转移到全局事务,反之亦然。
In all these cases, application code does not need to change. You can change how transactions are managed merely by changing configuration, even if that change means moving from local to global transactions or vice versa.
1.3。 用事务同步资源
1.3. Synchronizing Resources with Transactions
现在应该清楚如何创建不同的事务管理器以及它们如何链接到需要与事务同步的相关资源(例如,将DataSourceTransactionManager连接到JDBC数据源,HibernateTransactionManager连接到Hibernate SessionFactory等等)。 本节描述应用程序代码(直接或间接使用诸如JDBC,Hibernate或JPA之类的持久性API)如何确保正确创建,重用和清理这些资源。 本节还讨论了如何(可选)通过相关的PlatformTransactionManager触发事务同步。
How to create different transaction managers and how they are linked to related resources that need to be synchronized to transactions (for example DataSourceTransactionManager to a JDBC DataSource, HibernateTransactionManager to a Hibernate SessionFactory, and so forth) should now be clear. This section describes how the application code (directly or indirectly, by using a persistence API such as JDBC, Hibernate, or JPA) ensures that these resources are created, reused, and cleaned up properly. The section also discusses how transaction synchronization is (optionally) triggered through the relevant PlatformTransactionManager.
1.3.1。 高级同步方法
1.3.1. High-level Synchronization Approach
首选方法是使用Spring最高级别的基于模板的持久性集成API,或者将本机ORM API与事务感知工厂bean或代理一起使用,以管理本机资源工厂。 这些事务感知解决方案在内部处理资源创建和重用,清理,资源的可选事务同步以及异常映射。 因此,用户数据访问代码不必解决这些任务,而是可以完全专注于非样板持久性逻辑。 通常,您使用本机ORM API或使用模板方法通过使用JdbcTemplate进行JDBC访问。 这些解决方案将在本参考文档的后续章节中详细介绍。
The preferred approach is to use Spring’s highest-level template based persistence integration APIs or to use native ORM APIs with transaction-aware factory beans or proxies for managing the native resource factories. These transaction-aware solutions internally handle resource creation and reuse, cleanup, optional transaction synchronization of the resources, and exception mapping. Thus, user data access code does not have to address these tasks but can focus purely on non-boilerplate persistence logic. Generally, you use the native ORM API or take a template approach for JDBC access by using the JdbcTemplate. These solutions are detailed in subsequent chapters of this reference documentation.
1.3.2。 低级同步方法
1.3.2. Low-level Synchronization Approach
诸如DataSourceUtils(用于JDBC),EntityManagerFactoryUtils(用于JPA),SessionFactoryUtils(用于Hibernate)等的类存在于较低级别。 当您希望应用程序代码直接处理本机持久性API的资源类型时,您可以使用这些类来确保获得正确的Spring Framework托管实例,(可选)同步事务,并且在此过程中发生的异常是 正确映射到一致的API。
Classes such as DataSourceUtils (for JDBC), EntityManagerFactoryUtils (for JPA), SessionFactoryUtils (for Hibernate), and so on exist at a lower level. When you want the application code to deal directly with the resource types of the native persistence APIs, you use these classes to ensure that proper Spring Framework-managed instances are obtained, transactions are (optionally) synchronized, and exceptions that occur in the process are properly mapped to a consistent API.
例如,在JDBC的情况下,您可以改为使用Spring的org.springframework.jdbc.datasource.DataSourceUtils类,而不是传统的JDBC方法来调用DataSource上的getConnection()方法,如下所示:
For example, in the case of JDBC, instead of the traditional JDBC approach of calling the getConnection() method on the DataSource, you can instead use Spring’s org.springframework.jdbc.datasource.DataSourceUtils class, as follows:
Connection conn = DataSourceUtils.getConnection(dataSource);
如果现有事务已经与其同步(链接)了连接,则返回该实例。 否则,方法调用将触发新连接的创建,该新连接(可选)与任何现有事务同步,并可在随后的同一事务中重用。 如前所述,任何SQLException都包含在Spring Framework CannotGetJdbcConnectionException中,Spring Framework是未经检查的DataAccessException类型的层次结构之一。 这种方法为您提供了比从SQLException轻松获得的更多信息,并确保跨数据库甚至跨不同持久性技术的可移植性。
If an existing transaction already has a connection synchronized (linked) to it, that instance is returned. Otherwise, the method call triggers the creation of a new connection, which is (optionally) synchronized to any existing transaction and made available for subsequent reuse in that same transaction. As mentioned earlier, any SQLException is wrapped in a Spring Framework CannotGetJdbcConnectionException, one of the Spring Framework’s hierarchy of unchecked DataAccessException types. This approach gives you more information than can be obtained easily from the SQLException and ensures portability across databases and even across different persistence technologies.
这种方法在没有Spring事务管理(事务同步是可选的)的情况下也可以工作,因此无论您是否使用Spring进行事务管理,都可以使用它。
This approach also works without Spring transaction management (transaction synchronization is optional), so you can use it whether or not you use Spring for transaction management.
当然,一旦您使用了Spring的JDBC支持,JPA支持或Hibernate支持,您通常不希望使用DataSourceUtils或其他帮助程序类,因为您通过Spring抽象工作比直接使用相关API更快乐。 例如,如果您使用Spring JdbcTemplate或jdbc.object包来简化JDBC的使用,则在幕后进行正确的连接检索,您无需编写任何特殊代码。
Of course, once you have used Spring’s JDBC support, JPA support, or Hibernate support, you generally prefer not to use DataSourceUtils or the other helper classes, because you are much happier working through the Spring abstraction than directly with the relevant APIs. For example, if you use the Spring JdbcTemplate or jdbc.object package to simplify your use of JDBC, correct connection retrieval occurs behind the scenes and you need not write any special code.
1.3.3。类TransactionAwareDataSourceProxy
1.3.3. TransactionAwareDataSourceProxy