`

Spring 3 transaction management

 
阅读更多

Spring 3 transaction management

转自:

http://blog.m1key.me/2010/06/spring-3-transaction-management.html
In this article I will show you how to handle transaction management with Spring.


Benefits of Spring Transaction Management


  • Very easy to use, does not require any underlying transaction API knowledge
  • Your transaction management code will be independent of the transaction technology
  • Both annotation- and XML-based configuration
  • It does not require to run on a server - no server needed

Great! Let's begin with some basic information you may want to skip if you already know about transactions.


Overview


Transactions ensure that the data in your application (in the data source) stays consistent. You should also be familiar with the ACIDconcept.

Now, in Java you can handle transactions with plain SQL, with plain JDBC (a bit higher level), using Hibernate (or any other ORM library), or on an even higher level - with EJB or, finally, Spring!

EJBs require an application server, but our application presented here - doesn't.


Programmatic vs. Declarative


Spring offers two ways of handling transactions: programmatic and declarative. If you are familiar with EJB transaction handling, this corresponds to bean-managed and container-managed transaction management.

Programmatic means you have transaction management code surrounding your business code. That gives you extreme flexibility, but is difficult to maintain and, well, boilerplate.

Declarative means you separate transaction management from the business code. You only use annotations or XML based configuration.

We say that:
  • programmatic management is more flexible during development time but less flexible during application life
  • declarative management is less flexible during development time but more flexible during application life


In this article...


We will focus on declarative management.

OK, a small description of what we want to achieve and how.

The goals:
  • A desktop application (i.e. it doesn't need a server)
  • Declarative transaction management with minimum XML

The means:
  • A Maven project created in Eclipse and making use of SpringIDE
  • Spring transaction management
  • Java with annotations enabled (I'm going to use Java 6)
  • JPA 2.0

We are going to build on the project I used in my previous post on Spring & JPA 2.0.


Transaction Manager


We must first specify that we want to use annotation driven transaction management.

1
<tx:annotation-driven transaction-manager="myTransactionManager" />

And, of course, the transaction manager itself:
1
2
3
<bean id="myTransactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
    <property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>

What we are using here is the JpaTransactionManager. There are more managers available:

It references a bean called entityManagerFactory. Here it is:

1
2
3
4
<bean id="entityManagerFactory"
    class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
    <property name="persistenceUnitName" value="Dogs" />
</bean>


Annotation based


@Transactional is the annotation you can use on any method of any bean and on the bean itself.

1
2
3
4
5
import org.springframework.transaction.annotation.Transactional;
// ...
@Transactional
public void doSomething(...
// ...

If you apply the annotation on the bean (i.e. on the class level), every public method will be transactional.

Note: Remember that it affects only Spring managed data sources (in our example whatever comes from the entity manager factory). If you get your data source outside of Spring, the @Transactional annotation will have no effect.


Where to put @Transactional


You should put this annotation on your business logic methods (service methods), not on DAO methods (unless you know what you're doing) - that's a rule of thumb. Normally a business method will call many DAO methods and those calls make only sense when made together, every single one or none (atomicity).


Transaction Propagation


Whenever a transactional method is called, a decision is made - what to do with the transaction. Create a new one? Use an existing one if it exists, otherwise create a new one? Use an existing one only if it exists, otherwise fail?

To make it possible for you to specify this, propagation behaviors exist.

1
2
3
4
5
6
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
// ...
@Transactional(propagation = Propagation.REQUIRED)
public void doSomething(...
// ...

See the behaviors:
  • REQUIRED - uses the existing transaction. If it doesn't exist, creates a new one
  • REQUIRES_NEW - must start a new transaction. If there's an existing one, it should be suspended
  • SUPPORTS - if there is a transaction, runs in it. If there isn't, it just runs outside transaction context
  • NOT_SUPPORTED - must not run in a transaction. If there's an existing one, it should be suspended
  • MANDATORY - must run in a transaction. If there isn't one, it throws an exception
  • NEVER - must not run in a transaction. If there's an existing one, an exception will be thrown
  • NESTED - if there is a transaction, it runs withing the nested transaction of it. Otherwise it runs in its own

It is up to you to decide which behavior is best for each method. REQUIRED is the default one.

Note: If you are using the XML setup for transactions, you can also configure these behaviors there instead of Java code.


Transaction Isolation


Concurrent transactions cause problems that might be difficult to investigate.
  • Lost update - two transactions both update a row, the second transaction aborts, both changes are lost
  • Dirty read - reading changes that are not yet committed
  • Unrepeatable read - a transactions read twice the same row, getting different data each time
  • Phantom read - similar to the previous one, except that the number of rows changed

Now, the perfect solution to these problems is maximum isolation, but in reality this would cost too much resources and could lead to deadlocks. So, instead, you will set one of five isolation levels (where the fifth one is actually the maximum isolation level):

  • DEFAULT - uses the default database isolation level
  • READ_UNCOMMITTED - dirty read, unrepeatable read, phantom read problems may occur, but not lost update
  • READ_COMMITTED - unrepeatable read, phantom read problems my occur
  • REPEATABLE_READ - phantom read problems my occur
  • SERIALIZABLE - all problems avoided! But performance is low

The default choice is DEFAULT.

HSQLDB 2.0 supports READ_COMMITTED and SERIALIZABLE levels (HSQLDB FAQ).


... and roll...back! Transaction Rollback


With Spring transaction management the default behavior for automatic rollback is this: Only unchecked exceptions cause a rollback. Unchecked exceptions are RuntimeExceptions and Errors.

1
2
3
4
5
import org.springframework.transaction.annotation.Transactional;
// ...
@Transactional
public void doSomething(...
// ...
Think about it for a second! Are you sure you understand what it does?
  • If the doSomething method terminates its execution naturally, with no exceptions, the transaction is committed
  • If the doSomething method or any other method it callsthrows any kind of exception that is caught within doSomething or this other method and not rethrown, the transaction is committed
  • If the doSomething method or any other method it callsthrows any kind of checked exception that is notcaught or is caught and rethrown, the transaction iscommitted (so everything up to the moment of the exception being thrown is persisted)
  • If the doSomething method or any other method it callsthrows any kind of unchecked exception that is notcaught, the transaction is rolled back (so nothing saved in this transaction is persisted)

That's the default behavior. However, you may want to change it for certain cases:
1
2
@Transactional(rollbackFor = IOException.class, noRollbackFor = RuntimeException.class)
public void doSomething(...
Here I asked the transaction manager to rollback for IOExceptions and not to rollback for RuntimeExceptions.

Note: If you are using the XML setup for transactions, you can also configure these rules there instead of Java code.


Our sample application


Spring beans file

You've seen it before.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
    xsi:schemaLocation="http://www.springframework.org/schema/beans
 
...
 
<tx:annotation-driven transaction-manager="myTransactionManager" />
 
<bean id="myTransactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
    <property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
 
<bean id="entityManagerFactory"
    class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
    <property name="persistenceUnitName" value="Dogs" />
</bean>
 
...

Using transactions

1
2
3
4
5
import org.springframework.transaction.annotation.Transactional;
// ...
@Transactional
public void doSomething(...
// ...

That's all!


What if you...


What if you are using Spring 1.x?

You have to use the classic AOP approach.org.springframework.transaction.interceptor.TransactionProxyFactoryBean might be your starting point.

What if you want to declare transactions in XML and not in the code?

You may want to go for something like this:

1
2
3
4
5
6
7
8
9
10
11
<tx:advice id="dogsTxAdvice" transaction-manager="myTransactionManager">
    <tx:attributes>
        <tx:method name="persistDog" />
    </tx:attributes>
</tx:advice>
 
<aop:config>
    <aop:pointcut id="dogsOperation"
        expression="execution(* me.m1key.springtx.beans.DogsBean.*(..))" />
    <aop:advisor advice-ref="dogsTxAdvice" pointcut-ref="dogsOperation" />
</aop:config>


Summary


That's it! Although the transactions themselves are by no means a trivial topic, Spring makes at least handling them easy.

I got my knowledge mostly from this book:
Spring Recipes: A Problem-Solution Approach
It helps me run this website if you buy this book through this link, thanks!

A brief intro to HSQLDB and how to use it in this app (Note that the project in that article is NOT a Maven project, but an Eclipse JPA one, so the project creating part doesn't matter)?

Read on: Remove JpaTemplate in favor of @PersistenceContext.

Download the source code for this article

分享到:
评论

相关推荐

    Spring攻略(第三版)源代码

    12. Spring Transaction Management 13. Spring Batch 14. Spring NoSQL and Big Data 15. Spring Java Enterprise Services and Remoting Technologies 16. Spring Messaging 17. Spring Integration 18. Spring ...

    跟我学spring3

    6. Spring Transaction Management:理解事务管理的基本原则,以及如何使用Spring声明式事务管理。 7. Spring Security:学习如何使用Spring Security保护你的应用程序,实现认证和授权。 通过《跟我学Spring3》的8...

    spring 3前6 章

    这一章会阐述Spring如何通过模板类简化数据操作,如JdbcTemplate和HibernateTemplate,以及如何利用Spring的Transaction Management来实现数据库事务的统一管理。 第五章:MVC框架 Spring MVC是Spring框架的一部分...

    Spring Framework API文档

    Spring Framework API文档。...它实现了很优雅的MVC,对不同的数据访问技术提供了统一的接口,采用IOC使得可以很容易的实现bean的装配,提供了简洁的AOP并据此实现Transaction Management,等等......

    Spring 3+mybatis jar

    - **Spring Transaction Management**:提供了统一的事务管理接口,支持编程式和声明式事务处理。 2. **MyBatis**: - **Mapper**:定义SQL语句和Java方法的映射,使得SQL与Java代码分离,提高可维护性。 - **...

    spring-framework-5.0.4.RELEASEspring-framework-5.0.4.RELEASE

    Spring是什么呢?首先它是一个开源的项目,而且目前非常活跃...它实现了很优雅的MVC,对不同的数据访问技术提供了统一的接口,采用IOC使得可以很容易的实现bean的装配,提供了简洁的AOP并据此实现Transaction Management

    Spring.Essentials.178398

    Explore Spring's comprehensive transaction support for declarative Transaction Management and its integration with Spring's data access abstractions Investigate Spring Data access mechanisms with ...

    spring的5中事物配置 介绍spring的5中事物配置

    3. **基于XML的声明式事务管理(Declarative Transaction Management via XML)** - 在XML配置文件中,可以使用`&lt;tx:advice&gt;`和`&lt;aop:config&gt;`或`&lt;aop:aspect&gt;`来定义事务通知和切点表达式,然后通过`&lt;aop:advisor&gt;...

    spring3.x项目开发(5-10)

    你将学习如何配置数据源,声明DAO接口,以及如何通过Spring的Transaction Management来管理事务。 最后,`chapter10`可能涵盖了Spring的高级话题,如消息支持(Message Driven POJOs)、集成测试或者Spring Boot的...

    Spring事务配置的五种方式

    3. **基于 XML 的声明式事务管理(XML-based Declarative Transaction Management)** 在 XML 配置文件中,你可以使用 `&lt;tx:annotation-driven&gt;` 或 `&lt;tx:advice&gt;` 元素来开启基于注解或基于 AOP 的事务管理。这种...

    spring3.0+hibernate3.3+mysql8.0

    集成Hibernate时,Spring通过声明式事务管理(Declarative Transaction Management)简化了事务的处理,使得开发者无需手动编写事务控制代码。 **Hibernate 3.3** 是一个流行的Java对象关系映射(Object-Relational...

    spring学习.zip

    它涵盖了Spring与MyBatis的整合配置,以及如何利用Spring的AOP和Transaction Management来处理事务,为读者提供了一个完整的解决方案。 4. **《Spring Boot开发实战.pdf》**:此书是Spring Boot的实战指南,不仅...

    struts1+spring1+hibernater3写的新闻管理系统后台

    5. **事务管理**:Spring的Transaction Management确保了数据操作的原子性和一致性,如在多条数据库操作之间保持事务。 6. **国际化与本地化**:Struts1支持多语言,可以根据用户选择显示不同的语言版本。 7. **错误...

    rest+spring+hibernate

    4. **Spring事务管理**:Spring的Transaction Management提供了声明式事务管理,通过@Transactional注解在方法级别控制事务边界。当发生异常时,Spring会自动回滚事务,确保数据的一致性。 5. **O2O_v1.0**:这个...

    spring3资料

    五、Transaction Management Spring3的事务管理分为编程式和声明式两种。编程式事务管理使用PlatformTransactionManager接口,需要在代码中显式调用开始、提交、回滚等事务操作。声明式事务管理基于AOP,只需在方法...

    spring framework 2.0 dist 资源文件

    同时,Spring的Transaction Management事务管理模块支持编程式和声明式事务控制,确保了数据的一致性。 此外,Spring MVC是Spring Framework中的Web层组件,提供了一种模型-视图-控制器的架构模式,用于构建高性能...

    springspring-framework-3.0.0.M2

    3. **AOP(面向切面编程)增强**:Spring 3.0.0.M2 对 AOP 进行了优化,支持更多的通知类型,如 @Before、@After、@Around 等,使得切面的定义更加灵活。同时,新增的 @AspectJ 支持,使得切面编程更加直观,可以在 ...

Global site tag (gtag.js) - Google Analytics