2017-06-14 54 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)

就是這樣。

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); 
}