아무래도 테이블 구조를 간단하게 하려다보니.. 결국 문제가 터졌다.


친구 관계 정보를 가진 테이블의 컬럼은


INT FRIEND_SEQ

VA(20) REQUEST_USER_ID

VA(20) TARGET_USER_ID

DATE REQUEST_DT

DATE APPROVE_DT

VA(1) APPROVED_YN


친구 관계는 내(로그인 사용자)가 친구 요청을 했을 수도 있고, 내게 온 친구 요청을 수락한 경우도 있다.

이걸 직관적으로 내 친구들만 모으려고 하니 SQL을 잘 모르는 상태에서 저기서 친구들만 꺼내오려고 하다가

골치 좀 썩인 것 같다.

WHERE 절에서 두개의 SELECT문.. 하나는 


SELECT f.target_user_id FROM tb_friend f WHERE f.request_user_id = #loginUserId#


또 다른 하나는


SELECT f.request_user_id FROM tb_friend f WHERE f.target_user_id = #loginUserId#



이 두개 결과를 OR로 하여 중복제거하고 친구 목록을 가져왔는데, 잘 몰라도 이건 아니다 싶어 조인으로 할 방법을 찾아서 바꿨다.


SELECT

   ...

FROM

   tb_friend f

   LEFT JOIN tb_user u ON u.user_id =

      CASE

         WHEN f.request_user_id = #loginUserId#

            THEN f.target_user_id

         ELSE f.request_user_id

      END

   ...

WHERE ...


이렇게 해결 할 수 있었다.

SQL을 겉핥기로 배우다보니.. 저게 퍼포먼스상에 문제가 있는지 어떤지는 더 공부해야지.




두번째 멘붕은 저렇게 만든 쿼리를 Oracle SQL Developer에서 날려서 테스트 했을 때는 정상적으로 잘 동작하고,

프로젝트 내에서도 ResultSet까지는 정상적으로 잘 만든다.


근데 NullPointerException이 계속 발생.. 문제는 iBatis를 이용해서 디버깅이 어렵다(내게는 ㅠ)


ResultSet과 ResultMap Class 사이에서 매핑을 하면서 발생하는 문제였는데.. 하도 안풀려서 멘토님께 여쭤봤더니.


"혹시 모델 클래스에 int 타입 있어? 결과값이 null일 때는 int로 변환할 수 없어서 그럴거야."


!

!!!


정확하셨다. 

해결. 으앙

근데 해결하자니 또 쿼리문이 지저분해져서 이대로 써도 될런지 모르겠다. 

쿼리문이 하드코딩이다.. -_-







+ 추가

어제 멘토님이 하신 말씀 중에 NVL을 못들어서... 아침에 듣곤 허탈하고 해탈한 웃음만 하하..

무식하면 몸이 고생이라더니, 딱 그짝이다.. ㅠㅠ

이랬던 쿼리가!

SELECT

f.friend_seq friend_seq,

f.request_user_id request_user_id,

f.target_user_id target_user_id,

f.request_dt request_dt,

f.approve_dt approve_dt,

u.user_id user_id,

u.user_name user_name,

u.email email,

u.mobile_no mobile_no,

u.nickname nickname,

u.profile_image_path profile_image_path,

p.play_type_code play_type_code,

c.user_id channel_user_id,

s.song_seq song_seq,

s.song_title song_title

FROM

tb_friend f

LEFT JOIN tb_user u ON u.user_id = 

CASE

WHEN f.request_user_id = #userId#

THEN f.target_user_id

ELSE f.request_user_id

  END

  LEFT JOIN tb_playing p ON p.user_id = u.user_id

LEFT JOIN tb_channel c ON c.channel_seq = 

CASE

WHEN p.channel_seq IS NULL

THEN 0

ELSE p.channel_seq

END

LEFT JOIN tb_song s ON s.song_seq =

CASE

WHEN p.song_seq IS NULL

THEN 0

ELSE p.song_seq

END

WHERE

(f.request_user_id = #userId# OR f.target_user_id = #userId#) AND f.approved_yn = 'Y'


이렇게 바뀌었다.

SELECT

f.friend_seq friend_seq,

f.request_user_id request_user_id,

f.target_user_id target_user_id,

f.request_dt request_dt,

f.approve_dt approve_dt,

u.user_id user_id,

u.user_name user_name,

u.email email,

u.mobile_no mobile_no,

u.nickname nickname,

u.profile_image_path profile_image_path,

p.play_type_code         play_type_code,

c.user_id channel_user_id,

NVL(s.song_seq, 0) song_seq,

s.song_title song_title

FROM

tb_friend f

LEFT JOIN tb_user u ON u.user_id = 

CASE

WHEN f.request_user_id = #userId#

THEN f.target_user_id

ELSE f.request_user_id

  END

  LEFT JOIN tb_playing p ON p.user_id = u.user_id

LEFT JOIN tb_channel c ON c.channel_seq = p.channel_seq

LEFT JOIN tb_song s ON s.song_seq = p.song_seq

WHERE

(f.request_user_id = #userId# OR f.target_user_id = #userId#) AND f.approved_yn = 'Y'



엉엉


간단하게 NVL함수에 대해 정리하자면

어떤 컬럼의 값이 널인 경우에 다른 값으로 대체하는 것을 말한다.


NVL(컬럼명, 대체할 값) 의 형식으로 사용하고 필요하다만 앨리어싱 하면 된다.


NVL은 오라클 DB에서 사용할 수 있고, MySql에서는 동일한 기능을 가진 ifnull 함수가 있다.


+ Recent posts