티스토리 뷰
오라클 시퀀스를 사용한 기능을 추가하던 중 시퀀스가 증가하지 않는 현상이 발생하였음.
간략한 작업 내용은 특정 시퀀스를 조회하여 보관하고
다시 동일한 시퀀스를 조회하여 함께 사용하는 작업이었음.
첫 번째 시퀀스 조회 시 증가된 번호를 가져왔으나
두 번째 시퀀스 조회 시 첫 번째에 조회된 번호가 그대로 들어있었음.
첫번째 시퀀스 조회 결과 : 1
두번째 시퀀스 조회 결과 : 1
해당 기능과 관련된 일부 소스는 아래와 같음.
MyBatis 영역
<select id="getSeq" resultType="int">
SELECT SEQ.NEXTVAL FROM DUAL
</select>
Repository 영역
TestDAO interface 작성 생략
@Repository
public class TestDAOImpl implements TestDAO{
@Override
public int getTestSeq() {
return selectOne("getSeq");
}
}
Service 영역
TestService interface 작성 생략
@Transactional(rollbackFor = Exception.class)
@Service
public class TestServiceImpl implements TestService {
@Autowired
TestDao testDao;
@Override
public void getTestSeq() {
//첫번째 시퀀스 호출
int firstSeq = testDao.getTestSeq();
int secondSeq = testDao.getTestSeq();
Logger.debug("첫번째 시퀀스 조회 결과 : " + firstSeq);
Logger.debug("두번째 시퀀스 조회 결과 : " + secondSeq);
//위에 값을 활용해서 진행
testDao.insert(...);
}
}
트랜잭션이 문제인가 싶어 @Transactional(propagation, isolation) 옵션에 대해서 변경해 보고 테스트해보았으나 현상은 동일하였음.
MyBatis의 Cache 관련 정보를 확인
Local Session Cache
세션이 생성될때 마다 로컬캐시를 생성하고
동일한 쿼리에 대한 결과는 캐시에서 조회하여 반환.
commit, rollback, insert, delete, update 동작 및 트랜잭션이 종료되면 캐시를 비움.
Second Level Cache
mapper namespace 단위로 적용 가능하고 옵션으로 사용여부 설정이 가능함.
MyBatis의 Cache 관련 옵션을 확인
<configuration>
<settings>
<setting name="cacheEnabled" value="false" />
</settings>
...
...
...
</configuration>
해당 옵션이 설정되어있기 때문에 Second Level Cache 기능은 사용하지 않고 있는 것으로 확인.
Local Session Cache 로 인해 동일한 결과가 나오는 것으로 추정.
해결방법
1.해당 쿼리 MyBatis 영역 flushCache 옵션 설정
<select id="getSeq" resultType="int" flushCache = true>
SELECT SEQ.NEXTVAL FROM DUAL
</select>
flushCache 옵션을 true로 설정해 주면 트랜잭션이 끝나지 않아도 재조회시 동일 쿼리 조회 시 캐시가 flush 되어 새로운 값을 가져오게 됨.
2. 서비스 계층이 아닌 컨트롤러 계층에서 채번하는 방법
컨트롤러에서 채번을 하게 되면 동일한 트랜잭션이 아니기 때문에 중복되는 값을 조회하지 않게 된다. 하지만 해당 기능을 호출하는 부분에 동일하게 작업을 해주어야 하는 게 작업영역이 커지면 공수가 많이 들게 됨.
3. 로직상 첫번째 채번 후 insert 작업 진행 후 두 번째 채번을 진행 후 비지니스 로직을 수정하는 방법
로컬캐시가 초기화되는 조건 중 하나인 commit, rollback, insert, delete, update 동작 및 트랜잭션이 종료를 활용하는 방법으로 서비스 계층의 비지니스 로직을 아래와 같이 변경할 수 있음.
Service 영역
TestService interface 작성 생략
@Transactional(rollbackFor = Exception.class)
@Service
public class TestServiceImpl implements TestService {
@Autowired
TestDao testDao;
@Override
public void getTestSeq() {
//첫번째 시퀀스 호출
int firstSeq = testDao.getTestSeq();
//위에 값을 활용해서 진행
testDao.insert(...);
int secondSeq = testDao.getTestSeq();
//위에 값을 활용해서 진행
testDao.insert(...);
Logger.debug("첫번째 시퀀스 조회 결과 : " + firstSeq);
Logger.debug("두번째 시퀀스 조회 결과 : " + secondSeq);
}
}
첫번째 시퀀스 조회 결과 : 1
두번째 시퀀스 조회 결과 : 2
'JAVA' 카테고리의 다른 글
[java] jdom xPath 호출 시 멈춤 현상 해결 (0) | 2024.10.11 |
---|---|
[java] 인코딩이 다른 시스템간 byte 데이터 주고받기 (1) | 2024.09.26 |
ObjectMapper 결과 값 주입이 안되는 경우 (0) | 2024.01.17 |
java RSA decryption is failed (bouncycastleprovider 관련) (1) | 2023.10.06 |
세션 일부 값 누락 현상 조치하기(세션 클러스터링) (0) | 2023.08.07 |
- Total
- Today
- Yesterday
- 깨짐
- spring
- JPA
- Oracle
- jQuery
- html
- WAS
- 날짜
- React
- web
- Linux
- 컨테이너
- btye
- docker
- 이벤트발생
- vscode
- Windows
- gradle
- JSON
- TLS
- parse
- SpringBoot
- jaxen
- Git
- Eclipse
- Java
- SQL
- SSL
- mybatis
- IMAGE
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |