欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Java for Web学习笔记(一零一):Spring框架中使用JPA(1)Transaction(上)

程序员文章站 2022-04-22 13:59:20
...

在spring中使用事务涉及的Bean

本学习将介绍一些在Spring中使用事务设计的Bean,有一个大致的概念认识,以便了解后面的代码。如果觉得枯燥,也可以在后面的学习中回过头来看。

  在之前的学习中,我们在每个方法中都要创建EntityManager,进行事务的开启、关闭、回滚,代码有些相当累赘。Spring的强项在于用标记来解决,标记为@org.springframework.transaction.annotation.Transactional或者@javax.transaction.Transactional,可以用于接口和类及其方法。

我们需要设置下面的bean来支持标记的使用

PlatformTransactionManager

  在Spring框架中,控制事务使用org.springframework.transaction.PlatformTransactionManager,我们在root上下文中定义它,这样就可以通过标记自动地进行事务的启动,commit、抛出RuntimeException时回滚等。Spring提供下面两个PlatformTransactionManager:

  1. org.springframework.orm.jpa.JpaTransactionManager,最标准和最常用的PlatformTransactionManager。管理的事务只用于一个持续化单元,只用于EntityManger的动作。这满足大部分的场景
  2. 如果使用多个persistence units或者事务跨多个类型的资源(例如包括EntityManager和Java Message Service资源),需要使用org.springframework.transaction.jta.JtaTransactionManager或其子类WebLogicJtaTransactionManager(用于webLogic服务器),WebSphereUowTransactionManager (WebSphere服务器)。JTA(Java Transaction API)提供者,因此对于非完全Java EE服务器(如tomcat)需要一个复杂的JTA配置,因此书建议如果使用多个数据源,不建议采用tomcat,而采用完全的J2EE服务器。

SharedEntityManagerBean

  在之前的学习中,我们先获取了EntityManager,然后再开启transaction。而spring框架则采用org.springframework.orm.jpa.support.SharedEntityManagerBean作为EntityManager的proxy,确保transaction使用唯一的EntityManager(entityManager在同一时刻,只被一个transaction所使用)在同一线程中运行,即thread-safe。注入这个EntityManager proxy的方式为:
@PersistenceContext //我们这里不使用@Inject,因为这是从proxy中获取的在同一事务内唯一的entityManager,而不是同一个entityManager实例。
EntityManager entityManager;

//我们还可以在使用不同的Entity Proxy,对应多个persistence context configurations
public class FooRepository{
    @PersistenceContext(unitName = "fooUnit")
    EntityManager entityManager;
    ...
}
public class BarRepository{
    @PersistenceContext(unitName = "barUnit")
    EntityManager entityManager;
    ...
}

异常归整:PersistenceExceptionTranslator

  在使用JDBC开发中,不同数据库厂家的SQLException扩展均不同,因此处理起来很麻烦。HAP定义了一个基于PersistenceException的异常,但仍忽略了很多(例如key重复),对于NoSQL而言,每个client library都有自己的异常,导致问题更为复杂。Spring框架及其相关的数据工具通过继承org.springframework.dao.DataAccessException解决这个问题,无论使用JDBC,Hibernate或其他O/RM,JPA,Java Data Object或者NoSQL。

  在root上下文中定义一个或者多个org.springframework.dao.support.PersistenceExceptionTranslator的实现,实现可以配置支持多种持续化技术。如果配置了多个实现,Spring将自动chains它们。

  org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean是翻译JPA异常的,包括底层的JDBC错误代码。

  当定义了PersistenceExceptionTranslator的实现,例如LocalContainerEntityManagerFactoryBean,的对于标记了@Repository,调用其方法所产生的异常将被翻译。注意和@Async一样,不能在类内部生效,只能对外部调用类方法时生效。


相关链接:我的Professional Java for Web Applications相关文章