JPA事务和REST服务:良好实践

时间:2013-03-12 14:42:32

标签: java spring jpa cxf

我正在编写一个提供REST服务(使用Apache-CXF)的应用程序来管理JPA实体(使用Hibernate)。

我对交易管理感到有些失落,并希望就此话题提出建议。

目前,我在业务REST服务和较低服务之间放置了一个中间层,仅用于事务管理。

目前,我的代码看起来很像:

@Service 
class PersistanceService<MyBusinessClass>{
   MyBusinessClass load(Long id);
   void save(MyBusinessClass businessObject);
}

@Service 
class BusinessService<MyBusinessClass>{
   void doSomethingOn(MyBusinessClass businessObject);
}

@Service
class TransactionBusinessService<MyBusinessClass>{
   @Transactional
   void doSomethingOn(Long id) {
      MyBusinessClass businessObject = persistanceService.load(id);
      businessService.doSomethingOn(businessObject);
      persistanceService.save(businessObject);
   }
}

@Service
@path("/foo")
class RESTService {
   @Path("/doSomething")
   void doSomethingOn(Long id) {
      transactionBusinessService.doSomethingOn(id);
   }
}

我认为 TransactionBusinessService 过度。我希望''Spring''或''CXF''为我处理事务:我觉得请求是一个很好的粒度:在每个请求开始时初始化一个实体管理器,并在最后提交更新

我尝试将 @Transactional 注释添加到REST方法本身,但它似乎被忽略,或与CXF冲突。

  1. 您认为在请求级别委派交易并且不再为此烦恼是不是一个好主意?
  2. 如何让Spring或CXF将事务管理绑定到对我的请求?
  3. 先谢谢你的建议。

1 个答案:

答案 0 :(得分:3)

  

您是否认为在请求级别委派交易并且不再为此烦恼?

通常这不是个好主意,因为:

  • 通常分开事务隔离
  • 并不方便
  • 如果您需要在for-loop中进行一些更改,每个更改都必须拥有自己的交易,那么它也不是 透明的;同时在服务层,您可以决定是否需要整个循环是事务性的还是每次迭代;
  • 如果你直接在控制器中使用AOP注释,那么
  • tx:annotation-driven(以及其他一些AOP拦截器)有时会有点不可预测(至少我在Spring MVC / struts2和其他一些框架中遇到过这样的问题)< / LI>

基本上,你有3层:

  • 持久层,负责仅存储/获取数据;
  • 服务层,负责数据准备和AOP注释(@Transactional@PreAuthorize@Cacheable等),它们使用持久层;
  • 控制器级别,获取请求,绑定业务模型,可能验证它,将模型传递给服务层并从那里返回结果或处理异常
  

如何让Spring或CXF将事务管理绑定到对我的请求?

请确保您:

  • 您的配置中有适当的TransactionManager('org.springframework.transaction.PlatformTransactionManager`实施)
  • 您的配置中有tx:annotation-driven
  • 这些bean在您的CXF服务配置中可见
    <bean name="txManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory"/>
    </bean>

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