μ€νλ§μ AOPλ₯Ό ν΅ν΄ νΈλμμ (@Transactional)μ λ€λ£¨λ€ 보면 κ°μ μμ μ μ§ννλ©΄μ μ΄μ νΈλμμ μμλ°κ±°λ(REQUIRE), μλ‘μ΄ νΈλμμ μ μ΄μ΄μ μ²λ¦¬ν΄μΌνλ(REQUIRE_NEW)μΌμ΄ λ°μνκ² λμμ΅λλ€.
νΈμΆμ§μ μμ νΈλμμ μ μ νμ μΌλ‘ μ¬μ©ν μ μλλ‘ νκΈ° μν νΈλμμ μ²λ¦¬λ₯Ό μν monadic container type μ ꡬνν΄ λ³΄μμ΅λλ€.
@Transactional
public UserEntity saveUser(String userName) {
UserEntity userEntity = new UserEntity();
userEntity.setUserName(userName);
return userRepository.save(userEntity);
}
public void run() {
saveUser("testUserName");
}
@Transactional
μ΄λ
Έν
μ΄μ
μ μ¬μ©νμ¬ νΈλμμ
μ²λ¦¬λ₯Ό νκ³ μΆμ ν΄λμ€, νΉμ λ© μλμμ νΈλμμ
μ μ¬μ© ν μ μμμ΅λλ€.
μ΄λ₯Όν΅ν΄μ μ½κ³ κ°λ μ± μ’μ μ½λλ₯Ό 지 μ μμμ§λ§, μ±λ₯ νλμ΄λ μλ‘μ΄ κΈ°λ₯ μΆκ° λ±μ μν©μμ κ°μ μλΉμ€μμ DB νΈλμμ μ μ§§κ² κ°μ Έκ°κΈ° μν΄μ λΆλ¦¬νκ±°λ λ€λ₯Έλ°©μμ failoverλ₯Ό μννκΈ° μν΄μ μλ‘μ΄ νΈλμμ μ μ΄μ΄μΌνλ μꡬμ¬νμ΄ μκΈ°κ² λμμ΅λλ€.
μ΄λ @Transactional(propagation = Propagation.REQUIRES_NEW)
λ₯Ό μΆκ°ν μλ‘μ΄ λ©μλλ₯Ό μΆκ° νλκ²κ³Ό κ°μ΄ AOPλ§μΌλ‘λ μ΄λ¬ν μꡬμ¬νμ μννλλ° λ§μ μ΄λ €μμ΄ μμμ΅λλ€.
// AOP
/*@Transactional
public UserEntity saveUser(String userName) {
UserEntity userEntity = new UserEntity();
userEntity.setUserName(userName);
return userRepository.save(userEntity);
}*/
public Transaction<UserEntity> saveUser(String userName) {
return Transaction.create(() -> {
UserEntity userEntity = new UserEntity();
userEntity.setUserName(userName);
return userRepository.save(userEntity);
})
}
public void run() {
// saveUser("testUserName"); AOP
saveUser("testUserName")
. execute(transactionManager, Propagation.REQUIRE); // νΈλμμ
맀λμ μ Propagation μ€μ
}
Transaction<T>
κ° νΈμΆλλ λΆλΆ execute
μμ νΈλμμ
맀λμ μ Propagationμ μ§μ ν΄μ€μΌλ‘μ¨ νΈλμμ
μ μ’λ μμ λ‘κ² λ€λ£° μ μκ² λμμ΅λλ€.
public class Transaction<T> implements TransactionPublisher {
private final Function<Void, T> action;
private Transaction(Function<Void, T> action) {
this.action = action;
}
public static <T> Transaction<T> create(Callable<T> callable) {
return new Transaction<>(aVoid -> silentCallable(callable));
}
public static Transaction<Void> create(Runnable runnable) {
return new Transaction<>(aVoid -> {
runnable.run();
return null;
});
}
public <U> Transaction<U> map(Function<? super T, ? extends U> mapper) {
return new Transaction<>(action.andThen(mapper));
}
public <U> Transaction<U> flatMap(Function<? super T, ? extends Transaction<U>> mapper) {
return new Transaction<>(aVoid -> {
Transaction<U> apply = action.andThen(mapper).apply(null);
return apply.get();
});
}
private T get() {
return action.apply(null);
}
@Override
public T execute(PlatformTransactionManager platformTransactionManager, Propagation propagation) {
TransactionTemplate txTemplate = new TransactionTemplate(platformTransactionManager);
txTemplate.setPropagationBehavior(propagation.value());
return txTemplate.execute(status -> action.apply(null));
}
@SneakyThrows
private static <T> T silentCallable(Callable<T> callable) {
return callable.call();
}
}
public interface TransactionPublisher<T> {
T execute(PlatformTransactionManager platformTransactionManager, Propagation propagation);
}
νΈλμμ
λ΄λΆμμ μ€νλ μ½λλ₯Ό Function<Void, T> action
μΌλ‘ κ°μ§κ³ μκ³ μ€μ μ½λκ° μ€νλλ μμ μΈ Transaction#execute
μμ νΈλμμ
맀λμ μ Propagationμ μ£Όμ
λ°λλ‘ νμμ΅λλ€.
public Transaction<UserEntity> saveUser(String userName) {
return Transaction.create(() -> {
UserEntity userEntity = new UserEntity();
userEntity.setUserName(userName);
return userRepository.save(userEntity);
})
}
public void run() {
// saveUser("testUserName"); AOP
saveUser("testUserName")
.flatMap(u -> saveUser("testUserName"))
. execute(transactionManager, Propagation.REQUIRE); // νΈλμμ
맀λμ μ Propagation μ€μ
}
flatMap
μ μ΄μ©νμ¬ Transaction<T>
λ₯Ό μ°κ²°ν¨μΌλ‘μ¨ κ°μ νΈλμμ
μμ μ€ν ν μ μμ΅λλ€.
νΈλμμ μ²λ¦¬λ₯Ό μν monadic containerλ₯Ό λ§λ€μ΄ 보μμ΅λλ€. μ΄λ₯Ό ν΅ν΄μ νΈμΆλλ μμ μ νΈλμμ μ μμλ°κ±°λ, μλ‘μ΄ νΈλμμ μ μ€ννλκ²μ μ νμ μΌλ‘ μ¬μ© ν μ μκ² λμμ΅λλ€.
μ¬μ ν κΈ°λ³Έμ μΌλ‘λ μ’λ μ΅μν @Transactional
μ μ΄μ©ν νΈλμμ
μ²λ¦¬λ₯Ό κΈ°λ³ΈμΌλ‘ μ¬μ©νκ³ μμ§λ§ νμν μ₯μμ Transaction<T>
μ μ΄μ©ν ν¨μν νΈλμμ
μ μ¬μ©ν¨μΌλ‘μ¨ λͺ
μμ μΌλ‘ ννν νμκ° μλκ³³μ μ’λ κΉλνκ² μ²λ¦¬ ν μ μμμ΅λλ€.
μ μμ€μ½λλ GitHub - namjug-kim/functional-transaction λ₯Ό ν΅ν΄μ λ³΄μ€ μ μμ΅λλ€.