2017-06-14 19 views
1

は、私が持っているものです。JDBIトランザクションここ

UserDao

public interface UserDao { 
    @SqlUpdate("...") 
    int action1(@BindBean(..)) 

    @SqlUpdate("...") 
    int action2(@BindBean(..)) 
} 

のUserManager

public class UserManager { 
    private final UserDao dao; 

    public UserManager (final UserDao dao) { 
     this.dao = dao; 
     // there are other daos and clients passed here 
    } 

    @Transaction 
    public void foo() { 
     action1(); 
     action2(); 
    } 
} 

UserRepository

public class UserRepository { 
    private final UserManager manager; 

    public UserRepository(final UserManager manager) { 
     this.manager = manager; 
    } 

    public void doSomething() { 
     manager.foo(); 
    } 
} 

@Transactionは何もしません。ここにある構造のトランザクションサポートを追加するにはどうすればよいですか?

答えて

1

あなたが欲しいものを行うための正しい方法は次のとおりです。

  1. あなたがトランザクションメソッド本体からDBIのインスタンスへのアクセスを持っている必要があります。メソッドパラメータとして渡すか、サービスインスタンスフィールドとして渡します。
  2. トランザクション・メソッド内で、コールバックを渡してdbi.inTransaction(...)(または結果を返す必要がない場合はdbi.useTransaction(...))を呼び出します。このメソッドで@Transactionalアノテーションを使用する必要はありません。コールバックで
  3. 、それだあなたが

handle.attachで(YourDaoInterface.class)を必要とするすべてのDAOのインスタンスを取得します。

UPD。 だから、あなたのコードは、(あなたがJava8以降を使用すると仮定した場合)のようになります。

public class UserManager { 

private final DBI dbi; 

public UserManager (final DBI dbi) { 
    this.dbi = dbi; 
    // there are other daos and clients passed here 
} 

public void foo() { 
    dbi.useTransaction((handle, transactionStatus) -> { 
     UserDao dao = handle.attach(UserDao.class); 
     dao.action1(); 
     dao.action2(); 
    }); 
    } 
} 

ここでは、そのようなサービスメソッドのユニットテストを書くために使用するJUnit + Mockitoコードです:

@RunWith(MockitoJUnitRunner.class) 
........ 

@Mock 
private Handle handle; 

@Mock 
private UserDao userDao; 

@Spy 
private DBI dbi = new DBI(mock(ConnectionFactory.class)); 

@InjectMocks 
private UserManager userManager; 

@Before 
public void setUpDbi() { 
    Mockito.doReturn(handle) 
      .when(dbi).open(); 
    Mockito.when(handle.attach(UserDao.class)) 
      .thenReturn(userDao); 

    TransactionStatus status = Mockito.mock(TransactionStatus.class); 

    Answer<Object> transactionalAnswer = invocation -> 
      ((TransactionCallback) invocation.getArguments()[0]) 
        .inTransaction(handle, status); 

    Mockito.when(handle.inTransaction(any())) 
      .thenAnswer(transactionalAnswer); 
} 
関連する問題