Spring 사무 실효 장면 원리 및 해결 방안
같은 종류의 OrderServiceImpl 에서 doSomething()방법 은 사무 가 존재 하지 않 습 니 다.이 방법 은 본 클래스 에 존재 하 는 사무 주해 의 insert AndUpdateOrder Info()방법 을 호출 합 니 다.그러나 insert AndUpdateOrder Info()는 예상 한 사무 성 을 보장 할 수 없다.
열 인증:
OrderServiceImpl.insertAndUpdateOrderInfo 방법 중 upateData(updateParam)에 이상 이 발생 했 을 때 insertData(insertParam)에서 스크롤 백 이 발생 하지 않 았 습 니 다.
설명:자신 이 호출 할 때 아래 의 어떤 전파 속성 이 든 모두 무효 입 니 다.자신 이 호출 할 때의 하위 방법 은 AOP 대리 에 의 해 아래 의 두 가지 방식 으로 차단 되 지 않 기 때문에 모두 검증 을 거 쳐 하위 방법 업무 의 유효성 을 보장 할 수 없습니다.
@Transactional(propagation = Propagation.REQUIRES)
@Transactional(propagation = Propagation.REQUIRES_NEW)
@Controller
@RequestMapping("/trans")
public class TransactionalController {
@Autowired
OrderService orderService;
@RequestMapping("/test.do")
@ResponseBody
public void getIndex(HttpServletRequest request, HttpServletResponse response, Model model) {
orderService.doSomeThing();
}
}
@Service
public interface OrderService {
/*
*
* */
public void doSomeThing();
}
@Service
public class OrderServiceImpl implements OrderService {
@Autowired
TransBusiness transBusiness;
@Override
public void doSomeThing() {
insertAndUpdateOrderInfo();
}
@Transactional(propagation = Propagation.REQUIRED)
public void insertAndUpdateOrderInfo(){
Date date = new Date();
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String updateTime = dateFormat.format(date);
// 1:
String[] insertParam = {"555555555", "977723233", updateTime, updateTime};
transBusiness.insertData(insertParam);
// 2:
String[] updateParam = {"1111111111", updateTime, "1"};
transBusiness.upateData(updateParam);
}
}
@Service
public class TransBusiness {
@Autowired
JdbcTemplate dalClient;
public void insertData(String[] param) {
Map<String, Object> resultMap = new HashMap<>();
String sql = "INSERT INTO test_order (`order_no`, `cust_no`,create_time,update_time) VALUES (?, ?,?,?)";
int i = dalClient.update(sql, param);
System.out.println("TransBusiness>>>insertData" + i);
resultMap.put(" ", i);
}
public void upateData(String[] param) {
Map<String, Object> resultMap = new HashMap<>();
String sql = "update test_order set order_no =?,update_time=? ? where id= ?";
int i = dalClient.update(sql, param);
System.out.println("TransBusiness>>>upateData" + i);
resultMap.put(" ", i);
}
}
2.1 자체 호출 트 랜 잭 션 실효 해결 방법 1-부모 방법 에 트 랜 잭 션 추가
doSomething()방법 에 사무 성 을 추가 하면 1 중 사무 자체 호출 이 실 효 된 문 제 를 해결 할 수 있 습 니 다.
열 인증:
OrderServiceImpl.insertAndUpdateOrderInfo 방법 에서 1 단계 가 실 행 된 후 데이터베이스 에 이 주문 기록 이 존재 하지 않 습 니 다.2 단계 가 실 행 될 때 이상 이 발생 하여 전체 업무 가 다시 굴 러 갔다.설명 재 방법 은 1 자체 호출 업무 의 실효 문 제 를 해결 했다.
설명:이 곳 의@Transactional 은@Transactional(propagation=Propagation.REQUIRED)과 같 습 니 다.현재 사 무 를 지원 합 니 다.사무 가 없 으 면 새 사 무 를 만 듭 니 다.이것 은 일반적인 선택 이자 spring 기본 트 랜 잭 션 전파 입 니 다.
@Override
@Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class)
public void doSomeThing1() {
insertAndUpdateOrderInfo();
}
public void insertAndUpdateOrderInfo(){
Date date = new Date();
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String updateTime = dateFormat.format(date);
// 1:
String[] insertParam = {"8888888888", "977723233", updateTime, updateTime};
transBusiness.insertData(insertParam);
// 2:
String[] updateParam = {"1111111112", updateTime, "1"};
transBusiness.upateData(updateParam);
}
2.2 자체 호출 트 랜 잭 션 실효 해결 방법 2-트 랜 잭 션 방법 을 다른 유형 으로 나 눕 니 다.
@Service
public class TransBusiness {
@Autowired
JdbcTemplate dalClient;
@Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class)
public void insertAndUpdateOrderInfo(){
Date date = new Date();
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String updateTime = dateFormat.format(date);
// 1:
String[] insertParam = {"8888888888", "977723233", updateTime, updateTime};
insertData(insertParam);
// 2:
String[] updateParam = {"1111111112", updateTime, "1"};
upateData(updateParam);
}
}
3.SQL 규범 은 1992 년 에 데이터베이스 사무 격 리 단 계 를 제 시 했 고 이 를 통 해 병행 작업 데이터 의 정확성 과 일치 성 을 확보 했다.Mysql 의 사무 격 리 단 계 는 낮은 것 에서 높 은 것 으로 다음 과 같은 몇 가지 로 나 눌 수 있 습 니 다.1)READ UNCOMMITTED(제출 되 지 않 은 데 이 터 를 읽 기)
이것 은 가장 안전 하지 않 은 단계 입 니 다.조회 문 구 는 잠 금 이 없 는 상태 에서 실 행 됩 니 다.제출 되 지 않 은 다른 데 이 터 를 읽 고 더러 운 읽 기 를 합 니 다.제출 되 지 않 은 사무 데이터 가 모두 굴 러 갑 니 다.그 전에 이 업무 의 데 이 터 를 읽 은 것 은 더러 운 데이터 입 니 다.이런 수치 가 일치 하지 않 아 읽 은 위 해 는 상상 할 수 있 습 니 다.
2)READ COMMITTED(제출 한 데 이 터 를 읽 기)
하나의 사 무 는 데이터베이스 에 제출 된 데이터 만 읽 을 수 있 고 더러 운 읽 기 문 제 를 해결 할 수 있 으 나 중복 읽 을 수 없습니다.즉,한 사무 에서 두 번 의 조회 가 되 돌아 오 는 데 이 터 는 다 릅 니 다.첫 번 째 조회 금액 이 100 이 라면 두 번 째 조회 가 50 일 수 있 습 니 다.이것 은 중복 읽 을 수 없습니다.
3)REPEATABLE READ(데 이 터 를 중복 읽 을 수 있 습 니 다.이것 도 Mysql 의 기본 격 리 단계 입 니 다)
한 트 랜 잭 션 에서 두 번 의 잠 금 없 는 조회 가 되 돌아 오 는 데 이 터 는 모두 같 지만 다른 트 랜 잭 션 의 추가 데이터 도 읽 을 수 있 습 니 다.예 를 들 어 다른 사무 가 데 이 터 를 삽입 하여 제출 했다.이 사 무 는 두 번 째 로 읽 으 러 갔 을 때 이전에 조회 한 데이터 목록 에 존재 하지 않 는 데이터 가 하나 더 있 는 것 을 발견 했다.이때 가 바로 전설의 환상 적 인 읽 기 이다.이 단 계 는 중복 읽 기 를 피 할 수 있 지만 환 독 문 제 는 피 할 수 없다.
4)SERIALIZABLE(직렬 읽 기 가능)
이것 은 효율 이 가장 낮 고 자원 을 가장 많이 소모 하 는 사무 단계 로 반복 적 으로 읽 을 수 있 는 것 과 유사 하지만 자동 제출 모드 가 닫 힌 상황 에서 직렬 적 으로 읽 을 수 있 는 것 은 모든 조회 에 공유 자물쇠 와 배타 자 물 쇠 를 추가 하 는 것 은 모든 읽 기 작업 사이 에 막 히 지 않 음 을 의미 하지만 읽 기 작업 은 다른 업무 의 쓰기 작업 을 막 고 쓰기 작업 도 읽 기 작업 을 막 을 수 있다.
4.spring 사무 관 리 는 데이터 베 이 스 를 봉인 한 것 일 뿐 이 고 5 가지 사무 격 리 등급 과 7 가지 사무 전파 체 제 를 제시 했다.
4.1 음성 사무(declarative transaction management)는 Spring 이 제공 하 는 프로그램 사무 관리 방식 중 하나 이다.Spring 은 AOP 를 사용 하여 성명 식 사무 관 리 를 완성 합 니 다.따라서 사 운 드 사 무 는 방법 단위 입 니 다.Spring 의 사무 속성 은 자 연 스 럽 게 사 무 를 방법 에 응용 하 는 전략 을 설명 하 는 데 있 습 니 다.Spring 에서 사무 속성 은 다음 과 같은 매개 변수 가 있 습 니 다.
readOnly 속성의 상세 한 이해:
1)readonly 는 모든 데이터 베 이 스 를 지원 하 는 것 이 아니 라 데이터 베이스 에 따라 다른 결과 가 있 을 수 있 습 니 다.
2)readonly 를 설정 하면 connection 은 readonly 를 부여 하고 효 과 는 데이터 뱅 크 의 실현 에 달 려 있다.
a.Oacle 에서 테스트 한 결과 readOnly 가 지원 되 지 않 습 니 다.즉,Connection 의 readOnly 속성 이 true 든 false 든 SQL 의 첨삭 검사 에 영향 을 주지 않 습 니 다.
b.my sql 에서 테스트 한 결과 readOnly 를 지원 하 는 것 을 발 견 했 습 니 다.true 로 설정 되 었 을 때 만 조회 할 수 있 습 니 다.삭제 수정 하면 다음 과 같은 이상 이 발생 할 수 있 습 니 다.
Caused by: java.sql.SQLException: Connection is read-only. Queries leading to data modification are not allowed
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:910)
at com.mysql.jdbc.PreparedStatement.execute(PreparedStatement.java:792)
3)ORM 에서 readonly 를 설정 하면 Hibernate 에서 flush 가 금지 되 는 등 추가 적 인 최적화 가 부 여 됩 니 다.
4.2 spring 의 5 가지 사무 격 리 단계
1) ISOLATION_DEFAULT(백 엔 드 데이터베이스 기본 격 리 단계 사용)
다음 네 개 와 JDBC 의 격 리 단 계 는 다음 과 같다.
2) ISOLATION_READ_UNCOMMITTED(제출 되 지 않 은 변경 사항 을 읽 을 수 있 습 니 다.더러 운 읽 기,환영 읽 기 또는 중복 읽 을 수 없습니다)
3) ISOLATION_READ_COMMITTED(이미 제출 한 병렬 트 랜 잭 션 에서 읽 을 수 있 습 니 다.더러 운 읽 기 를 방지 할 수 있 지만,환영 읽 기와 중복 읽 기 불가 가 발생 할 수 있 습 니 다)
4) ISOLATION_REPEATABLE_READ(같은 필드 에 대한 여러 번 읽 은 결 과 는 현재 트 랜 잭 션 자체 가 바 뀌 지 않 는 한 일치 합 니 다.더러 운 읽 기와 중복 읽 기 를 방지 할 수 있 으 나 환영 읽 기 는 여전히 발생 할 수 있다)
5) ISOLATION_SERIALIZABLE(ACID 의 격 리 단계 에 완전히 복종 하여 더러 운 읽 기,중복 읽 기,환영 읽 기 가 발생 하지 않도록 확보한다.이것 은 모든 격 리 단계 에서 도 가장 느 립 니 다.왜냐하면 이것 은 보통 현재 사무소 와 관련 된 데이터 표를 완전히 잠 그 는 것 을 통 해 이 루어 지기 때 문 입 니 다)
4.3 spring 의 7 가지 사무 전파 메커니즘:
1)REQUIRED(업무 필요):업무 방법 은 하나의 업무 에서 실행 되 어야 합 니 다.방법 이 실 행 될 때 이미 하나의 업무 에 있 으 면 이 업무 에 가입 하 십시오.그렇지 않 으 면 스스로 새로운 사 무 를 만 듭 니 다.이것 은 spring 의 기본 전파 행위 입 니 다.
2) NOT_SUPPORTED(사무 지원 하지 않 음):성명 방법 은 업무 가 필요 합 니 다.방법 이 업무 와 관련 이 없 으 면 용 기 는 사 무 를 열지 않 습 니 다.방법 이 한 업무 에서 호출 되면 이 사 무 는 걸 립 니 다.방법 호출 이 끝 난 후에 원래 의 사 무 는 다시 실 행 됩 니 다.
3) REQUIREDS_NEW(새로운 사무 가 필요 합 니 다):업무 방법 은 항상 자신 을 위해 새로운 사 무 를 시작 합 니 다.만약 에 방법 이 한 업무 에서 실행 되 었 다 면 원래 의 업무 가 끊 기 고 새로운 사무 가 생 성 되 었 습 니 다.방법 이 끝 날 때 까지 새로운 사무 가 끝나 야 원래 의 업무 가 다시 실 행 될 수 있 습 니 다.
비고:새 트 랜 잭 션 이 이상 캡 처 되 지 않 으 면 원래 트 랜 잭 션 방법 도 스크롤 백 됩 니 다.(이 결론 은 자가 측정 검증 을 거 쳤 다)
4)MANDATORY(강제 적 인 사무):존재 하 는 사무 에서 만 수행 할 수 있 습 니 다.업무 방법 은 자신의 업 무 를 시작 할 수 없 으 며,업무 방법 이 업무 가 없 는 환경 에서 호출 되면 이상 을 버린다.
5)NEVER(사무 가 존재 할 수 없습니다):성명 방법 은 절대 사무 범위 내 에서 실 행 될 수 없습니다.만약 방법 이 특정한 사무 범위 내 에서 실 행 될 경우 용 기 는 이상 을 버 립 니 다.업무 와 관련 이 없어 야만 정상적으로 실 행 됩 니 다.
6)SUPPORTS(지원 업무):업무 방법 이 특정한 업무 범위 내 에서 호출 되면 방법 은 이 업무 의 일부분 이 되 고 업무 방법 이 업무 범위 밖에서 호출 되면 방법 은 업무 가 없 는 환경 에서 실 행 됩 니 다.
7)NESTED(끼 워 넣 기 사무):하나의 이벤트 가 존재 하면 끼 워 넣 은 사무 에서 실 행 됩 니 다.활성 화 된 사무 가 없 으 면 REQUIRED 속성 에 따라 실 행 됩 니 다.하나의 단독 사 무 를 사 용 했 습 니 다.이 사 무 는 스크롤 백 할 수 있 는 보증 점 이 여러 개 있 습 니 다.내부 사 무 는 외부 사무 에 영향 을 주지 않 고 DataSourceTransactionManager 사무 관리자 에 만 효과 가 있 습 니 다.
사고:Nested 와 Requires New 의 차이 점:
a.RequiresNew 는 매번 새로운 독립 된 물리 사 무 를 만 들 고 Nested 는 하나의 물리 적 사무 만 있 습 니 다.
b.Nested 내장 트 랜 잭 션 스크롤 백 이나 제출 은 외부 트 랜 잭 션 을 스크롤 백 하거나 제출 하지 않 지만 외부 트 랜 잭 션 스크롤 백 은 내장 트 랜 잭 션 을 스크롤 백 합 니 다.RequiresNew 는 모두 새로운 트 랜 잭 션 이기 때문에 관련 이 없습니다.
c.Nested 는 JDBC 3 의 저장 점 을 사용 하여 이 루어 집 니 다.즉,저 버 전 드라이브 를 사용 하면 내장 사 무 를 지원 하지 않 습 니 다.
실제 응용 에 서 는 기본 적 인 트 랜 잭 션 전파 행 위 를 사용 하고 가끔 Requires New 와 Nested 방식 을 사용 합 니 다.
이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
[MeU] Hashtag 기능 개발➡️ 기존 Tag 테이블에 존재하지 않는 해시태그라면 Tag , tagPostMapping 테이블에 모두 추가 ➡️ 기존에 존재하는 해시태그라면, tagPostMapping 테이블에만 추가 이후에 개발할 태그 기반 ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.