Spring事務抽象的關鍵是事務策略的概念。事務策略定義在`org.springframework.transaction.PlatformTransactionManager`接口里:
~~~java
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)相同。 僅此優勢,即使您使用JTA,Spring Framework事務也是值得抽象的。 與直接使用JTA相比,可以更輕松地測試事務代碼。
與Spring的理念保持一致,任何PlatformTransactionManager接口的方法拋出的TransactionException都是未經檢查的(也就是說,它擴展了java.lang.RuntimeException類)。 交易基礎設施故障幾乎總是致命的。 在極少數情況下,應用程序代碼實際上可以從事務失敗中恢復,應用程序開發人員仍然可以選擇捕獲并處理TransactionException。 重點是開發人員不會被迫這樣做。
`getTransaction(..)`方法返回`TransactionStatus`對象,依賴于`TransactionDefinition`參數。 返回的`TransactionStatus`可能表示新事務,或者如果當前調用堆棧中存在匹配的事務,則可以表示現有事務。 后一種情況的含義是,與Java EE事務上下文一樣,`TransactionStatus`與執行線程相關聯。
` TransactionDefinition` 接口的特點:
* 傳播: 一般一個事務內的代碼都運行在同一個事務內,當然也可以暫停當前事務,新建事務,參考[事務傳播](https://docs.spring.io/spring/docs/5.0.7.RELEASE/spring-framework-reference/data-access.html#tx-propagation)
* 隔離:此事務與其他事務的工作隔離的程度。 例如,此事務是否可以看到來自其他事務的未提交的寫入?
* 超時:此事務在多久之后由底層事務自動回滾。
* 只讀狀態:當您的代碼讀取但不修改數據時,可以使用只讀事務。 在某些情況下,只讀事務可能是一種有用的優化,例如在使用Hibernate時。
這些設置反映了標準的事務概念。 如有必要,請參閱討論事務隔離級別和其他核心事務概念的資源。 理解這些概念對于使用Spring Framework或任何事務管理解決方案至關重要。
`TransactionStatus`接口為事務代碼提供了一種控制事務執行和查詢事務狀態的簡單方法。 應該熟悉這些概念,因為它們對于所有事務API都是通用的:
~~~java
public interface TransactionStatus extends SavepointManager {
boolean isNewTransaction();
boolean hasSavepoint();
void setRollbackOnly();
boolean isRollbackOnly();
void flush();
boolean isCompleted();
}
~~~
無論在spring中使用聲明式或編程式的事務管理,正確定義`PlatformTransactionManager `的實現都是非常重要的.一般是通過依賴注入定義實現.
`PlatformTransactionManager `的實現一般需要了解工作的環境:JDBC, JTA, Hibernate等等.
定義jdbc數據源
~~~xml
<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 `引用`DataSource `
~~~xml
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
~~~
如果你使用JTA在java企業級容器中,那么需要使用`JtaTransactionManager`通過JNDI獲取`DataSource`:
~~~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: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`,它使用容器的全局事務管理.
也可以簡單的使用Hibernate 的局部事務管理,需要定義Hibernate 的`LocalSessionFactoryBean`,用于獲取Hibernate 會話實例
`DataSource `的配置同jdbc,這里就不再贅述.`HibernateTransactionManager `需要引用`SessionFactory`
~~~xml
<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 并且也使用了全局事務JTA,如下配置
~~~xml
<bean id="txManager" class="org.springframework.transaction.jta.JtaTransactionManager"/>
~~~
- 正確打開本書的姿勢
- 第一部分 Core
- 1. Ioc container
- 1.1. Introduction to the Spring IoC container and beans
- 1.2. Container overview
- 1.2.1. Configuration metadata
- 1.2.2. Instantiating a container
- 1.2.3. Using the container
- 1.3. Bean overview
- 1.3.1. Naming beans
- 1.3.2. Instantiating beans
- 1.4. Dependencies
- 1.4.1. Dependency Injection
- 1.4.2. Dependencies and configuration in detail
- 1.4.3. Using depends-on
- 1.4.4. Lazy-initialized beans
- 1.4.5. Autowiring collaborators
- 1.4.6. Method injection
- 1.5 Bean Scopes
- 1.6. Customizing the nature of a bean TODO
- 1.7. Bean definition inheritance TODO
- 1.8. Container Extension Points TODO
- 1.9. Annotation-based container configuration
- 1.9.1. @Required
- 1.9.2. @Autowired
- 1.9.3. Fine-tuning annotation-based autowiring with @Primary
- 1.9.4. Fine-tuning annotation-based autowiring with qualifiers TODO
- 1.9.5. Using generics as autowiring qualifiers TODO
- 1.9.6. CustomAutowireConfigurer TODO
- 1.10. Classpath scanning and managed components
- 1.10.1. @Component and further stereotype annotations
- 1.11. Using JSR 330 Standard Annotations TODO
- 1.12. Java-based container configuration
- 1.12.1. Basic concepts: @Bean and @Configuration
- 1.12.2. Instantiating the Spring container using AnnotationConfigApplicationContext
- 2. Resources
- 2.1. Introduction
- 2.2. The Resource interface
- 2.3. Built-in Resource implementations
- 2.3.1. UrlResource
- 2.3.2. ClassPathResource
- 2.3.3. FileSystemResource
- 2.3.4. ServletContextResource
- 2.3.5. InputStreamResource
- 2.3.6. ByteArrayResource
- 2.4. The ResourceLoader
- 2.5. The ResourceLoaderAware interface
- 2.6. Resources as dependencies
- 2.7. Application contexts and Resource paths
- 2.7.1. Constructing application contexts
- 2.7.2. Wildcards in application context constructor resource paths
- 2.7.3. FileSystemResource caveats
- 3. Validation, Data Binding, and Type Conversion
- 4. Spring Expression Language (SpEL)
- 5. Aspect Oriented Programming with Spring
- 5.1. Introduction
- 5.1.1. AOP concepts
- 5.1.2. Spring AOP capabilities and goals
- 5.1.3. AOP Proxies
- 5.2. @AspectJ support
- 5.2.1. Enabling @AspectJ Support
- 5.2.2. Declaring an aspect
- 5.2.3. Declaring a pointcut
- 5.2.4. Declaring advice
- 5.2.5. Introductions TODO
- 5.2.6. Aspect instantiation models TODO
- 5.2.7. Example
- 5.3. Schema-based AOP support TODO
- 5.4. Choosing which AOP declaration style to use TODO
- 5.5. Mixing aspect types TODO
- 5.6. Proxying mechanisms
- 5.6.1. Understanding AOP proxies
- 5.7. Programmatic creation of @AspectJ Proxies
- 5.8. Using AspectJ with Spring applications
- 5.8.1. Using AspectJ to dependency inject domain objects with Spring
- 5.8.2. Other Spring aspects for AspectJ
- 第二部分 Testing
- 第三部分 Data Access
- 1. Transaction Management
- 1.1. Introduction to Spring Framework transaction management
- 1.2 Advantages of the Spring Framework’s transaction support model
- 1.2.1. Global transactions
- 1.2.2. Local transactions
- 1.2.3. Spring Framework’s consistent programming model
- 1.3. Understanding the Spring Framework transaction abstraction
- 1.4. Synchronizing resources with transactions
- 1.4.1. High-level synchronization approach
- 1.4.2. Low-level synchronization approach
- 1.4.3. TransactionAwareDataSourceProxy
- 1.5. Declarative transaction management
- 1.5.1. Understanding the Spring Framework’s declarative transaction implementation
- 1.5.2. Example of declarative transaction implementation
- 1.5.3. Rolling back a declarative transaction
- 1.5.4. Configuring different transactional semantics for different beans
- 1.5.5. tx:advice元素的 settings
- 1.5.6. Using @Transactional
- 1.5.7. Transaction propagation
- 1.5.8. Advising transactional operations
- 1.5.9. Using @Transactional with AspectJ TODO
- 第四部分 web servlet
- 第五部分 Web Reactive
- 第六部分 Integration
- 第七部分 Languages