@ Transactional 실효 장면 및 원리
6114 단어 spring
@Service
public class UserServiceImpl extends BaseServiceImpl implements UserService {
@Autowired
private UserMapper userMapper;
@Override
@Transactional
public void insertOne() {
UserEntity userEntity = new UserEntity();
userEntity.setUsername("Michael_C_2019");
//
userMapper.insertSelective(userEntity);
//
throw new IndexOutOfBoundsException();
}
@Override
public void saveOne() {
insertOne();
}
}
실패 의 원리: @ Transactional 은 동적 에이전트 대상 을 바탕 으로 이 루어 집 니 다. 클래스 내부 에서 의 방법 호출 은 this 키 워드 를 통 해 이 루어 집 니 다. 동적 에이전트 대상 을 거치 지 않 았 기 때문에 트 랜 잭 션 스크롤 이 실 효 됩 니 다.3. @ Transactional 방법 내부 에서 이상 을 잡 았 습 니 다. catch 코드 블록 에서 이상 을 다시 던 지지 않 았 고 트 랜 잭 션 도 굴 러 가지 않 았 습 니 다.코드 는 다음 과 같 습 니 다:
@Override
@Transactional
public void insertOne() {
try {
UserEntity userEntity = new UserEntity();
userEntity.setUsername("Michael_C_2019");
//
userMapper.insertSelective(userEntity);
//
throw new IndexOutOfBoundsException();
} catch (IndexOutOfBoundsException e) {
e.printStackTrace();
}
}
그래서 알 리 바 바 의 자바 개발 자 매 뉴 얼 에 명확 한 규정 이 있 습 니 다. @ Transactional 방법 에서 이상 을 잡 았 습 니 다. 수 동 으로 스크롤 백 해 야 합 니 다. 코드 는 다음 과 같 습 니 다.
@Override
@Transactional
public void insertOne() {
try {
UserEntity userEntity = new UserEntity();
userEntity.setUsername("Michael_C_2019");
//
userMapper.insertSelective(userEntity);
//
throw new IndexOutOfBoundsException();
} catch (IndexOutOfBoundsException e) {
e.printStackTrace();
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
}
}
실패 원리: 이때 spring 의 소스 코드 를 살 펴 보 겠 습 니 다: Transaction AspectSupport 류 의 invoke WithinTransaction 방법
TransactionAspectSupport
@Nullable
protected Object invokeWithinTransaction(Method method, @Nullable Class> targetClass, TransactionAspectSupport.InvocationCallback invocation) throws Throwable {
TransactionAttributeSource tas = this.getTransactionAttributeSource();
TransactionAttribute txAttr = tas != null ? tas.getTransactionAttribute(method, targetClass) : null;
PlatformTransactionManager tm = this.determineTransactionManager(txAttr);
String joinpointIdentification = this.methodIdentification(method, targetClass, txAttr);
Object result;
if (txAttr != null && tm instanceof CallbackPreferringPlatformTransactionManager) {
TransactionAspectSupport.ThrowableHolder throwableHolder = new TransactionAspectSupport.ThrowableHolder(null);
try {
result = ((CallbackPreferringPlatformTransactionManager)tm).execute(txAttr, (status) -> {
TransactionAspectSupport.TransactionInfo txInfo = this.prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);
Object var9;
try {
Object var8 = invocation.proceedWithInvocation();
return var8;
} catch (Throwable var13) {
if (txAttr.rollbackOn(var13)) {
if (var13 instanceof RuntimeException) {
throw (RuntimeException)var13;
}
throw new TransactionAspectSupport.ThrowableHolderException(var13);
}
throwableHolder.throwable = var13;
var9 = null;
} finally {
this.cleanupTransactionInfo(txInfo);
}
return var9;
});
if (throwableHolder.throwable != null) {
throw throwableHolder.throwable;
} else {
return result;
}
} catch (TransactionAspectSupport.ThrowableHolderException var19) {
throw var19.getCause();
} catch (TransactionSystemException var20) {
if (throwableHolder.throwable != null) {
this.logger.error("Application exception overridden by commit exception", throwableHolder.throwable);
var20.initApplicationException(throwableHolder.throwable);
}
throw var20;
} catch (Throwable var21) {
if (throwableHolder.throwable != null) {
this.logger.error("Application exception overridden by commit exception", throwableHolder.throwable);
}
throw var21;
}
} else {
TransactionAspectSupport.TransactionInfo txInfo = this.createTransactionIfNecessary(tm, txAttr, joinpointIdentification);
result = null;
try {
result = invocation.proceedWithInvocation();
} catch (Throwable var17) {
// , catch
this.completeTransactionAfterThrowing(txInfo, var17);
throw var17;
} finally {
this.cleanupTransactionInfo(txInfo);
}
this.commitTransactionAfterReturning(txInfo);
return result;
}
}
그 는 이상 을 포착 하고 catch 에서 사 무 를 스크롤 백 하 는 사람 이기 때문에 자신의 방법 에서 catch 가 이상 하 다 면 catch 에서 새로운 이상 을 던 지지 않 으 면 사 무 는 스크롤 백 하지 않 을 것 이다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
thymeleaf로 HTML 페이지를 동적으로 만듭니다 (spring + gradle)지난번에는 에서 화면에 HTML을 표시했습니다. 이번에는 화면을 동적으로 움직여보고 싶기 때문에 입력한 문자를 화면에 표시시키고 싶습니다. 초보자의 비망록이므로 이상한 점 등 있으면 지적 받을 수 있으면 기쁩니다! ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.