개발일기장

Java 데이터 접근 기술 - transaction & exception(Check,UnCheck) (3) 본문

JAVA

Java 데이터 접근 기술 - transaction & exception(Check,UnCheck) (3)

게슬 2023. 2. 8. 23:13
728x90

 

SQLP자격증 공부하는 것 때문에 DB단에서의 transaction은 많이 봤었는데

웹서버 단에서는 따로 공부를 하지 않았음..

그냥 쿼리에 for update를 사용한다거나, 아니면 서버에서 transaction시작 ~ 끝  소스코드 추가하는 정도..


일단 모든  transaction의 시작은 connection을 받아오는것으로 부터 시작됨

그리고 그 connection같은 경우 jdbc에서 interface에서 추상화 되어있기 때문에 로직이랑 완벽?하게 분리 할 수 있음

conn.setAutoCommit(false);
/*
connection을 사용한 logic의 수행
select 문에서 for update를 사용하지 않으면 굳이 저렇게 사용할 필요는 없긴함
DML 을 위한 작업임
*/
if( 성공시 ){
	conn.commit();
} else {
	conn.rollback();
}

and finally(release connection )

대충 이런식으로 하나의 connection에서 날라가는 query가 바로바로 적용되지 않고 해당 로직이 종료 될 떄 까지 db 캐시에 저장이 되었다가 commit을 하게되면 적용이 되는 그런 방식임

코드만 봐도 지저분하고 저런부분이 많이 발생하면 전체적으로 관리하기가 힘들 수 있다.

그리고 jdbc계열을 사용하면 저렇게 해도 되는데 JPA같은 기술로 변경을 할 경우 저 부분을 완전 뜯어 고쳐야 하는 상황이 발생함..

그래서 스프링에서는 이거를 깔끔하게 관리를 해주는데 이거 정리하는거는 spring관련된건 다 안할거라 패스해야지..

스프링에서는 AOP 방식으로 이러한 것들을 다 추상화/proxy로 만들어줘서 짱 편하다고 한다.


Exception

Throwable: 최상위 예외, 하위에 Exception과 Error가 있다.

Error: 심각한 시스템 오류와 같은 애플리케이션에서 복구 불가능한 시스템 예외 -> 개발자가 이것을 잡으려하면 안됨

-> 그래서 throwable로 catch를 하게 되면 error까지 걸리니깐 하지마셈

Exception: 로직에서 활용할 수 있는 실질적인 예외임. 이거 밑에는 컴파일러가 체크하는 check exception임

RuntimeException: 런타임예외. 컴파일러가 체크하지 않는다. ex)NullPointerException같이 compiler에서 확인할 수 없고 프로세스가 돌아가면서 걸리게 되는거

 

Exception을 다룰때 그 function에서 catch하고 처리하거나 그 function을 호출한 상위 function으로 throw해야한다.

끝까지 예외를 처리하지 못하게 되면?

1. 일반적인 Java main() thread의 경우 로그를 출력하면서 프로세스가 종료됨

2. 웹 어플리케이션의 경우 WAS가 해당 예외를 마지막에 받아서 처리하고 오류 메시지를 보여줌

 

일단 두개의 Exception을 만들자. 하나는 Exception상속, 하나는 RuntimeException 상속

public class MyRuntimeException extends RuntimeException{
    public MyRuntimeException(String message) {
        super(message);
    }
}
public class MyCheckException extends Exception{
    public MyCheckException(String message) {
        super(message);
    }
}

 

그리고 이것을 던지는 method도 각각 하나씩 만들자

public void exceptionRepository () throws MyCheckException {
    throw  new MyCheckException("check Exception throw");
}

public void runtimeExceptionRepository () throws MyCheckException {
    throw  new MyRuntimeException("check Exception throw");
}

그리고 이것을 호출하는 method도 하나씩...

public void service1(){
    exceptionRepository();
}
public void service2(){
    runtimeExceptionRepository();
}

 

빨간줄

그런대 여기까지만 코드를 작성해도 service1의 경우(exception 호출)빨간줄로 뜨면서 Unhandled exception으로 나온다.

문제X

그리고 service2(runtime Exception)은 문제가 없음

이 소스코드를 컴파일 해보면

caught or declared to be thrown

service1에서 발생한 exception을 잡거나 던져서 처리해라는 애러가 발생함

// try catch 하거나
public void service1(){
    try{
        exceptionRepository();
    }catch (MyCheckException me){
        me.printStackTrace();
    }
}
// 밖으로 던지거나
public void service1_1() throws MyCheckException{
    exceptionRepository();
}

그래서 이렇게 처리를 해줘야 한다.

이것을 main thread에서 실행시켜보자

1. service1() -> try, catch한 곳

2.service1_1() -> throws한 곳 -> main에서도 throws함

Exception in thread "main"

3.service2() -> 아무것도 명시안함 (throws, try-catch)

1,2,3 다 비슷한 내용이다.

 

결론 

체크 예외와 언체크 에외의 차이는 예외를 처리할 수 없을 때 밖으로 던지는 부분에 있음.

컴파일 단계에서 필수로 throws, try-catch를 해야 하거나 or 그냥 냅둬도 exception발생하거나 그 이외에는 차이점이 없음.

 

그래서 일반적인 Exception의 경우 

-> 개발자가 반드시 확인해야하는 경우 check exception을 사용해서 실수로 예외를 놓치는 것을 막아줄 수 있다.

하지만 모든것을 throws, try-catch하기에는 너무 부담이 크다

 

jdbc를 사용해서 connection을 얻고 sql을 던질 때에는 ConnectException과, SQLException이 발생하는데 호출하는 부분마다 throw하고 try-catch를 한다고 해도 jdbc말고 jpa를 사용하게 되면 의존적인 부분들을 전부 수정해야하는 문제가 발생한다.

그래서 최근의 라이브러리들은 대부분 런타임 예외를 기본으로 설정한다..

 

RuntimeException의 경우

그냥 method를 호출한 부분에서 catch를 안해주면 그 위로 exception이 날라가서 원하는 부분에서 처리해 줄 수 있다.

-> main thread까지...

-> 웹서버에서는 WAS까지..

 


그런데 DB 밴더마다 connection을 유지해주는 방식이 다르고 이전 게시글에서 작성한 것 처럼 connection pool을 관리해주는 방식도 다르기 때문에 깊게 하면 복잡할 것 같다. 근대 깊게 해도 개발 단계에서는 잘 써먹지는 못할 것 같음

 

728x90

'JAVA' 카테고리의 다른 글

Proxy ...  (1) 2023.11.26
Reflection ...  (0) 2023.11.26
Java 데이터 접근 기술 - connection pool (2)  (0) 2023.02.06
Java 데이터 접근 기술 - jdbc (1)  (0) 2023.02.05
Java 데이터 접근 기술 (0)  (1) 2023.02.05
Comments