多个Sharded数据库Hibernate事务

时间:2015-12-11 13:51:43

标签: java spring hibernate transactions transactionmanager

我有一个基于Spring的tomcat服务。我使用基于注释的hibernate映射,我有多个分片数据库。所有分片数据库都有相同的表格,表示学生。我想使用@Transactional注释在它们上实现事务。

@Autowired
List<SessionFactory> sessionFactoryList;

@Transactional
public insertStudentBatch(List<Student> students) {

}

现在我要插入整批。如果发生任何错误,我希望所有错误都回滚。最好的方法是什么?我可以编写多个TransactionManager限定符,例如@Transactional("txManager1", "txManager2")吗?

1 个答案:

答案 0 :(得分:1)

不,不幸的是,spring @Transactional注释特定于单个事务管理器,并且不符合您所描述的愿望。

在我看来,您可能想要的是2PC提交的JTA事务,其中您基本上启动了主JTA事务,然后对于每个SessionFactory,您调用每个特定事务管理器以进行分片并执行你的运作。

 @Service
 public class StudentBatchServiceImpl implements StudentBatchService {
   @Autowired List<StudentService> studentServices;
   @Transactional(value = "jtaTransactionManager")
   public void storeStudents(List<Student> students) {
     for(StudentService service : studentServices) 
       service.storeStudents(students);
   }
 }

 public interface StudentService {
   void storeStudents(List<Student> students);
 }

 public abstract AbstractStudentServiceImpl implements StudentService {
   protected void storeStudents(EntityManager em, List<Student> students) {
     for(Student student : students) {
       em.persist(student);
     }
   }
 }

 @Service
 public class Shard1StudentServiceImpl extends AbstractStudentServiceImpl {
   @PersistenceContext(name = "shard1")
   private EntityManager entityManager;
   @Override
   @Transactional(value = "shard1TransactionManager")
   public void storeStudents(List<Student> students) {
     storeStudents(entityManager, students);
   }
 }

在没有使用JTA进行2PC提交设置的情况下,可能还有其他一些方法可以解决这个问题,但在容器管理事务(如JBoss,WebLogic等)中可能会出现问题。这就是方法。

作为一个侧栏,如果您已经沿着春天路径行进,我可能会建议您查看spring-batch。它为批量操作提供了一个不错的基线,用于过多的用例。我上面描述的是spring-batch内的一个案例的穷人实现。

<强>更新

如果您想避免必须使用注释详细信息创建多个shard类实现,则可以使用XML配置并使用单个类实现:

 <bean id="shard1" class="default.ShardStudentServiceImpl">
   <property name="entityManager" ref="shard1EntityManager" />
   <property name="transactionManager" ref="shard1TransactionManager" />
 </bean>

唯一的区别是你必须用XML定义25个分片,然后你必须编写自己的代码来启动,提交和管理ShardStudentServiceImpl类中的事务。

在上面显示的最终实现中将抽象基类与注释结合使用,我的更新到达同一目的地。实际上,如果查看spring-batch,您会注意到他们的批处理配置遵循类似的前提,即将实体管理器和事务管理器指定为单个类的输入属性。