fix: setParameter 가 실패한 LobCreator 를 닫지도 등록하지도 않는 문제 수정 - #373
Open
wantaekchoi wants to merge 1 commit into
Open
Conversation
setParameter 는 LobCreator 를 만든 뒤 setParameterInternal 이 성공해야 LobCreatorSynchronization 을 등록한다. 이 동기화가 beforeCompletion 에서 close 를 부르는 유일한 자리다. setParameterInternal 이 SQLException 이나 IOException 을 던지면 등록에 닿지 못하므로 그 LobCreator 는 닫히지 않는다. 클래스 Javadoc 은 LOB 을 쓰려면 트랜잭션 동기화가 활성이어야 하는 이유를 "LobCreator 를 닫는 동기화를 등록하기 위해서" 라고 적는다. 만든 LobCreator 는 반드시 닫힌다는 뜻이다. 같은 패키지의 BlobSerializableTypeHandler 도 ObjectOutputStream·ObjectInputStream 을 finally 에서 닫아 실패 경로를 함께 덮는다. DefaultLobHandler 는 createTemporaryLob 을 켜면 TemporaryLobCreator 를 돌려주고 그 close 가 만들어 둔 Blob·Clob 의 free 를 부른다. 닫히지 않으면 그만큼이 세션에 남는다. 등록 전에 빠져나가는 경우에만 닫도록 finally 를 두었다. 성공 경로의 동작은 그대로다.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
수정 사유 Reason for modification
수정된 소스 내용 Modified source
AbstractLobTypeHandler.setParameter가 만든LobCreator를 실패 경로에서 닫지 않습니다.성공 경로는 :107 에서 동기화를 등록하고 그 동기화의
beforeCompletion이 :192 에서close를 부릅니다. 이 클래스에서close를 부르는 자리는 :192 하나뿐입니다.실패 경로는 :107 에 닿지 못합니다.
setParameterInternal이SQLException을 던지면 그대로 전파되고IOException은 :104 에서SQLException으로 바뀌어 다시 던져집니다. 어느 쪽이든 그LobCreator는 닫히지도, 나중에 닫아줄 동기화에 등록되지도 않습니다.클래스 Javadoc(:36-37)이 트랜잭션 동기화를 요구하는 이유를 이렇게 적습니다.
만든
LobCreator는 닫는다는 자기 선언입니다. 같은 패키지의 형제BlobSerializableTypeHandler도ObjectOutputStream(:116-117)과ObjectInputStream(:144-145)을finally로 닫아 실패 경로까지 덮습니다.이 동기화 클래스의 Javadoc(:173-174)은 "Invokes LobCreator.close to clean up temporary LOBs that might have been created." 입니다. 이 모듈이 쓰는
spring-jdbc의DefaultLobHandler는createTemporaryLob을 켜면TemporaryLobCreator를 돌려주고, 그close가 만들어 둔Blob·Clob의free를 부릅니다. 닫히지 않으면 그만큼이 세션에 남습니다. 다만 실제 DB 세션에 남는 LOB 을 측정하지는 못했습니다.AS-IS / TO-BE
형제와 같이
finally로 정리하되, 동기화 등록 전에 빠져나가는 경우로 한정했습니다.성공 경로에서도 닫지 않는 이유는,
setParameter가 돌아온 뒤 실제 실행 시점에 드라이버가LobCreator가 넘긴 스트림을 읽기 때문입니다. 그 시점을 아는 것은 트랜잭션 동기화이므로 성공 경로는 지금처럼 등록만 하고 넘어갑니다.영향 범위
동작이 달라지는 것은
setParameterInternal이 예외를 던지는 경우뿐이고 성공 경로의 동작은 그대로입니다. 이setParameter는final이라 하위 클래스 3종(BlobByteArrayTypeHandler,ClobStringTypeHandler,BlobSerializableTypeHandler)이 모두 이 경로를 씁니다.JUnit 테스트 JUnit tests
드라이버가
PreparedStatement.setBytes에서SQLException을 내도록 해BlobByteArrayTypeHandler.setParameter를 실제로 태우고 진짜DefaultLobCreator를 감싼 프록시로close호출 횟수를 셉니다. 실패 뒤 등록된 동기화의beforeCompletion까지 모두 실행한 다음 세기 때문에, 직접 닫든 동기화에 등록하든 어느 처방이어도 통과합니다. 미수정 코드는 둘 다 하지 않아 0 회입니다.수정 전입니다.
수정 후 모듈 전체입니다.
테스트 브라우저 Test Browser
테스트 스크린샷 또는 캡처 영상 Test screenshots or captured video
화면이 없는 실행환경 모듈이라 첨부하지 않았습니다.