サービス層で宣言的トランザクションを扱いたい
// DAO
@Transactional
public class UserDAO implements UserDAOInterface {
@Inject
EntityManager em;
public User find(int id) {
return em.find(User.class, id);
}
@Override
public void update(User user) {
// TODO Auto-generated method stub
em.merge(user);
em.flush();
}
// こちらは正常にトランザクション処理が実行(ロールバック)される
public void transaction(User buyer, Item item) {
User seller = find(item.getSellerId());
int price = item.getPrice();
buyer.setBalance(buyer.getBalance() - price);
update(buyer);
if(true) {
throw new RuntimeException();
}
seller.setBalance(seller.getBalance() + price);
update(seller);
}
}
上記のDAOのtransactionメソッドを呼び出した場合は正常にロールバックされるのですが,
// サービス層(ビジネスロジック)
@Transactional
public class UserLogic implements UserLogicInterface{
UserDAOInterface dao = Guice.createInjector(new JpaPersistDaoModule())
.getInstance(UserDAO.class);
public User signIn(String email, String password) {
return dao.find(email, password);
}
// こちらは正常に実行(ロールバック)されない
public void transaction(User buyer, Item item) {
User seller = dao.find(item.getSellerId());
int price = item.getPrice();
buyer.setBalance(buyer.getBalance() - price);
dao.update(buyer);
if(true) {
throw new RuntimeException();
}
seller.setBalance(seller.getBalance() + price);
dao.update(seller);
}
}
こちら側のメソッドを呼び出した場合ではうまくいきませんでした(メソッドはコピー&ペースト).
実現したいのは後者のほうです(でないと,ビジネスロジックにEntityManagerを持たせかつそれをDAOのメソッドに引数として渡すという気持ちの悪いことをしなければなりません).よろしくお願いします.
補足です.
Google Guice と PostgresSQL を使用しています.