mof-brown

ずっとモフモフしてたい

Spring MVC で複数データソースを扱った場合の挙動を調べてみた

Spring MVC で扱うデータソースが2つある時、片方だけトランザクションを張った場合にもう片方の更新が反映されない、という問題に直面したので色々試してみた。Spring 初心者すぎて辛い。

環境

Spring 3.2.4

元々のソース

例えば user と groupというテーブルがあり、それぞれに対して更新する処理を書いていた。

#!java

@Service

public class HogeService {

@Transactional

public void update() {

userService.update();

groupService.update();

}

}

ここで、user と group とでDBを分けることになり、DataSource と TransactionManager を複数に分けた際、デフォルトの user は更新されるが group の更新がされなくなった。この挙動自体はまぁ当然。

(1) groupService 側にも @Transactional を指定してみる

これで両方トランザクションが張られて正常に動作した。

#!java

@Service

public class GroupService {

@Transactional(“group")

public void update() {

// update...

}

}

(2) afterCommit を利用してみる

今回は group 側にトランザクションを張らなくても良いケースだったので、試しに TransactionSynchronizationAdapter#afterCommit を利用してみた。

#!java

@Service

public class HogeService {

@Transactional

public void update() {

userService.update();

TransactionSynchronizationManager.registerSynchronization(

new TransactionSynchronizationAdapter() {

@Override

public void afterCommit() {

groupService.update();

}

}

);

}

}

これでうまくいくかと思ったが、group への更新は反映されなかった。何かイメージと違う。afterCommit の後に何か処理が走っているのか。

(3) user、group への更新処理をメソッド毎分ける

StackOverflow とか Spring 関連の記事を見ていると、結局これに落ち着きそうな感じ。もちろん想定通りに動作する。

#!java

@Service

public class HogeService {

@Transactional

public void updateUser() {

userService.update();

}

@Transactional(“group")

public void updateGroup() {

groupService.update();

}

}

時間も無く、結局うまいやり方が見つからないので、(3) の実装で一旦落ち着いた。