티스토리 뷰

오류 원인

전글에서의 오류 원인은 ImageService에 사진업로드 함수안에 System.out.println(imageEntity);가 문제였다 왜 그런걸까?

위부분을 주석하고 저장한뒤 사진 업로드하면 정상적으로 업로드가된다.

 

무한참조

1. imageEntity가 sysout실행

2. domain.image.image.java에 있는 모든 getter가 실행

3. image에 있는 User getter가 발생

4. image 안에 있는 List<Image> 안에 Image도 실행된다

다시 1,2 ,3 ,4 형태로 무한참조를 반복하게된다.

 

우리가 보통 sysout로 객채를 출력하게되면 알아서 .toString이 붙게된다. 

toString을 안만들었는데 어떻게 있냐면 @Data에서 알아서 만들어줘서 몰랐던것이다.

toString을 생성하면 생긴건 이러하다.

위 코드에서 return값에서 첫줄 맨뒤 user부분만 삭제를 해보자

그럼다시 syso에 imageEntity를 출력하게하고 다시 업로드를 해보자

확인해보면 잘 되는것을 확인할 수 있다.

여기서 느낄 수 있는점은 sysout과 무한참조를 조심해야한다

필요없는 변수저장과 출력은 최대한 지워주는게 좋습니다. 

 

요청이 진행되는 과정

1. 클라이언트가 보낸 요청을 디스패쳐가 받음

2. DB에 접근할 수 있는 세션이 생성되어 controller에 감

3. controller은 repository로 전해짐

4. repository에서 영속성 컨텍스트에게 요청을보내고 데이터가 있으면 바로 반환이 될것이고 

 없다면 DB에 요청을하고 영속성 컨텍스트에 저장이되고 repository에 돌아올것이다.

5.repository - service로 전해지고 service가 끝나는 시점에서 세션이 종료된다.

6. controller에서 세션이 사라졌으니 lazy로딩이 불가능하다

 

lazy로딩이란?

우리가 User클래스에서 images를 요청할때 fetch = FetchType.LAZY라고 지정하였다

이때 LAZY는 밑의 과정에서 db까지 가서 user를 영속성 컨텍스트에 저장하고 그뒤에 컨트롤로 돌아와서 db에 다시 image를 요청하게 되는데 세션이 그전에 끝난다면 db에 데이터를 요청 할 수가 없다 왜? 세션이 끝났으니까

 

 EAGER 을 사용한다면 어떠할까 사용가능하다 왜냐하면 EAGER은 DB에서 바로 같이 join요청을하여 영속성 컨텍스트에 user와 images가 같이 저장되기 때문이다.

 

open-in-view:false로 설정하게되면 세션이 service에서 controller로 돌아올때 세션이 종료되어서 image를 요청할수가 없게된다 하지만 open-in-view를 true로 설정하게된다면 컨트롤에서 디스패쳐로 전해질때 세션이 종료되게 되어 image요청이 가능하게 만들어진다.

 

@Transactional

DB에 반영되는 함수는 무조건 Transcrtional을 걸어주어야 한다 이유는

 

우리가 송금 서비스를 만들었다 해보자

밑과같은 데이터가 존재한다 

1단계 1번유저가 2번유저에게 5천원을 보냈다 그러면

2단계 2번의 유저는 35000이 되게된다 

하지만 만약 1단계는 성공을했다 2단계에서 실패를한다면? 5천원은 그냥 허공으로 증발한것이다 

(고객한태 바로 등짝 맞아야함)

이를 방지하기위해 우리는 @Transactional을 사용해야한다

트랜젝셔널의 기능은 하나가 성공하고 하나가 실패하면 전원 롤백시켜버린다 무조건 둘다 성공해야만 커밋을 한다.

알겠으면 만든 사진업로드에 @Transactional을 붙여주러 빨리가자 등짝맞기 싫으면

 

Select문에도 @Transactional을?

아니 DB에 반영되는 것만 @Transactional을 걸면 되는거 아니었나요?

이유는 여러가지가 있지만 한개만 말씀드리면

 

user1번정보를 update를 하고싶어서 

repository에서 영속성컨텍스트에 자료가 없으면 db로 요청하여 영속성 컨텍스트에 저장이되고 repository에 값이 들어오게 될것이다

이렇게되면 repository와 영속성컨텍스트와 db에는 모두 같은 자료로 동기화가 되어있을것이다

그리고

내가 repository에 user의 이름을 cos로 변경하면 영속성컨택스트에도 cos로 변경되게된다

이름은 service controller로 넘어가는 과정에서 영속성 컨택스트는 변경된 오브젝트를 db에 자동으로 flush하게된다

이때 영속성 컨택스트는 계속 오브젝트가 변경이되었는지 계속 더티체킹을하게된다 그래서 Transactional(readOnly=true)

을 걸어주게 되면 더티체킹을 하지 않게되어 필요없는 일을 할필요가 없게된다.

이외에도 여러 이유가 있지만 이번글에선 여기까지만 알아놓자.

 

 

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2025/05   »
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
글 보관함