package org.jdbi.v3.sqlobject.transaction.internal;
import java.lang.reflect.Method;
import org.jdbi.v3.core.Handle;
import org.jdbi.v3.core.HandleCallback;
import org.jdbi.v3.core.transaction.TransactionException;
import org.jdbi.v3.core.transaction.TransactionIsolationLevel;
import org.jdbi.v3.sqlobject.Handler;
import org.jdbi.v3.sqlobject.HandlerDecorator;
import org.jdbi.v3.sqlobject.transaction.Transaction;
public class TransactionDecorator implements HandlerDecorator {
@Override
public Handler decorateHandler(Handler base, Class<?> sqlObjectType, Method method) {
final Transaction txnAnnotation = method.getAnnotation(Transaction.class);
final TransactionIsolationLevel isolation = txnAnnotation.value();
final boolean readOnly = txnAnnotation.readOnly();
return (target, args, handle) -> {
Handle h = handle.getHandle();
if (h.isInTransaction() && h.isReadOnly() && !readOnly) {
throw new TransactionException("Tried to execute a nested @Transaction(readOnly=false) "
+ "inside a readOnly transaction");
}
HandleCallback<Object, Exception> callback = th -> base.invoke(target, args, handle);
final boolean flipReadOnly = readOnly != h.isReadOnly();
if (flipReadOnly) {
h.setReadOnly(readOnly);
}
try {
return h.inTransaction(isolation, callback);
} finally {
if (flipReadOnly) {
h.setReadOnly(!readOnly);
}
}
};
}
}