いいえ、残念ながら、Spring@Transactional
アノテーションは単一のトランザクション マネージャーに固有のものであり、説明したとおりに動作しません。
あなたが望む可能性が高いのは、基本的にマスターJTAトランザクションを開始し、次にそれぞれSessionFactory
に対して、シャードの特定のトランザクションマネージャーをそれぞれ呼び出して操作を実行する2PCコミットのJTAトランザクションです。
@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
。これは、多数のユースケースに対してバッチのような操作の適切なベースラインを提供します。上で説明したのは、 内の 1 つのケースの貧弱な実装ですspring-batch
。
アップデート
注釈の詳細を含む複数のシャード クラスの実装を作成する必要がないようにしたい場合は、XML 構成に頼って、単一のクラス実装を持つことができます。
<bean id="shard1" class="default.ShardStudentServiceImpl">
<property name="entityManager" ref="shard1EntityManager" />
<property name="transactionManager" ref="shard1TransactionManager" />
</bean>
ShardStudentServiceImpl
ここでの唯一の違いは、XML で 25 個のシャードを定義する必要があることと、クラス内でトランザクションを開始、コミット、および管理するための独自のコードを作成する必要があることです。
上記の最終的な実装でアノテーションと組み合わせて抽象基本クラスを使用すると、私の更新は同じ宛先に到着します。実際、 を見るとspring-batch
、エンティティ マネージャーとトランザクション マネージャーを単一のクラスへの入力プロパティとして指定することで、バッチ構成が同様の前提に従っていることがわかります。