package todowizard.core.guice; import java.lang.reflect.Method; import java.util.function.Supplier; import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; import org.seasar.doma.jdbc.tx.TransactionManager; import com.google.inject.Inject; /** * Guice でトランザクション管理を行うためのインターセプタ。<br /> * Guice のトランザクション管理機構として標準でサポートされているのは JPA だけなので、Doma2 の * {@link TransactionManager} を使った実装にする。 * * @author t_endo */ public class DomaLocalTxInterceptor implements MethodInterceptor { private static final DomaTransactional DEFAULT_TRANSACTIONAL = Internal.class .getAnnotation(DomaTransactional.class); @Inject private TransactionManager transactionManager; /** * {@inheritDoc} */ @Override public Object invoke(MethodInvocation invocation) throws Throwable { DomaTransactional transactional = readTransactionMetadata(invocation); Supplier<Object> supplier = () -> { // ラムダ式内で例外が起きた場合、ロールバックされる try { return invocation.proceed(); } catch (Throwable t) { throw new RuntimeException(t); } }; Object result; switch (transactional.attribute()) { case REQURED: result = transactionManager.required(supplier); break; case NOT_SUPPORTED: result = transactionManager.notSupported(supplier); break; case REQURES_NEW: default: result = transactionManager.requiresNew(supplier); break; } return result; } /** * 対象に付いている {@link DomaTransactional} アノテーションを取り出す。 * * @param methodInvocation * @return */ private DomaTransactional readTransactionMetadata( MethodInvocation methodInvocation) { Method method = methodInvocation.getMethod(); Class<?> targetClass = methodInvocation.getThis().getClass(); DomaTransactional transactional = method .getAnnotation(DomaTransactional.class); if (transactional == null) { transactional = targetClass.getAnnotation(DomaTransactional.class); } if (transactional == null) { transactional = DEFAULT_TRANSACTIONAL; } return transactional; } @DomaTransactional private static class Internal { } }