본문 바로가기

스터디 기록/SpringBoot 심화 스터디

Long 타입 비교와 동적 쿼리 그리고 Join

Long 타입 크기 비교 시 주의할 점

1) ==, equals() 차이 기억하기

Java에서 Long 타입은 객체로 취급되는 래퍼 클래스이다. 따라서 Long 객체를 비교할 때 참조 값 비교와 값 비교를 혼동하지 않도록 주의해야 한다.

- == : 객체를 비교할 때, 객체의 참조 주소를 비교한다. 따라서 값이 같더라도 참조 주소가 다르면 false를 반환한다.

- equals() : 객체를 비교할 때, 객체의 값 자체를 비교한다. 따라서 값이 같으면 참조 주소가 달라도 true를 반환한다. 

 

2) 되도록이면 longValue() 로 사용하기

Long 객체는 내부적으로 -128, 127까지의 값은 캐싱하여 동일한 객체를 재사용한다. 그러나 이 캐싱 범위를 벗어나는 값들은 새로운 객체로 생성되기 때문에 == 로 비교할 시 예상치 못한 결과가 발생할 수 있다. 따라서 longValue()를 사용해서 기본형 long 으로 변환한 뒤 비교하는 것이 안전하다.


JPA 동적 쿼리(Dynamic Query)란?

먼저 JPA는 엔티티를 통해 데이터베이스와 상호작용 할 수 있는 ORM 프레임워크이다. 정적 쿼리 뿐만 아니라, 다양한 조건이나 상황에 따라 쿼리가 변경되는 동적 쿼리를 작성할 수 있다. 

 

그럼 어떤 상황에 동적 쿼리가 사용될까?

 

1. 검색 조건이 유동적인 경우

: 사용자가 필터 옵션(이름, 나이, 이메일 등)을 선택하면 이에 따라 다른 조건의 검색 쿼리를 실행해야 할 때.

2. 필드 값이 복합적일 경우

: 특정 값이 존재하면 조건에 포함하고, 없으면 제외하거나 페이징 처리를 동적으로 설정해야 할 때.

3. 복잡한 쿼리를 조립해야 할 경우

: 여러 조건을 동적으로 추가하거나 조합해야 할 때.

 

JPA에서 동적 쿼리를 작성하는 방법

1. JPQL + 조건문

일단 JPQL 을 사용하여 기본적인 동적 쿼리를 작성할 수 있다. 하지만 조건문을 직접 하드 코딩해야 하므로 가독성이 떨어지고 유지보수가 어렵다. 조건이 복잡해질수록 오류 발생 가능성이 높아진다.

String jpql = "SELECT u FROM User u WHERE 1=1";
    if (name != null) {
        jpql += " AND u.name = :name";
    }
    if (age != null) {
        jpql += " AND u.age = :age";
    }
    Query query = em.createQuery(jpql, User.class);
    if (name != null) query.setParameter("name", name);
    if (age != null) query.setParameter("age", age);
    return query.getResultList();

 

2. QueryDSL

유명한 JPA 동적 쿼리 라이브러리로 QueryDSL이 존재한다. 가독성이 좋고 직관적인 코드로 동적 쿼리를 생성할 수 있다.

return queryFactory.selectFrom(user)
                   .where(builder)
                   .fetch();

Outer Join에 대해서

Outer Join은 방향 (Left, Right, Full) 에 따라 세 가지로 나뉜다.

 

1. Left (Outer) Join

왼쪽 테이블의 모든 데이터를 유지하고, 오른쪽 테이블의 데이터를 가져온다. 

오른쪽 테이블에 일치하는 왼쪽 데이터가 없으면 해당 부분이 NULL 값으로 채워진다.

 

2. Right (Outer) Join

오른쪽 테이블의 모든 데이터를 유지하고, 왼쪽 테이블의 데이터를 가져온다.

왼쪽 데이블에 일치하는 오른쪽 데이터가 없으면 해당 부분이 NULL 값으로 채워진다.

 

3. Full Outer Join

양쪽 테이블의 모든 데이터를 가져온다.

왼쪽 또는 오른쪽 테이블 중 없는 부분의 데이터는 NULL 값으로 채워진다.