DB 6

JPA Converter처럼, MyBatis TypeHandler로 변환 책임 한 곳에 모으기

들어가며Oracle의 DATE 타입은 사실 년-월-일 + 시:분:초까지 저장할 수 있지만, MyBatis는 기본적으로 LocalDateTime ↔ DATE 매핑을 지원하지 않습니다.처음에는 DB 컬럼 타입을 VARCHAR로 바꿀까, 혹은 Java에서 String으로 관리하고 SQL에서 TO_DATE로 변환할까 생각했습니다.하지만 이런 방식은 DB와 Java의 타입을 억지로 다르게 가져가는 것이고, 결국 일관성이 깨지고 유지보수성이 떨어질 수 있습니다.반대로, DB의 컬럼 타입과 Java의 타입을 최대한 동일하게 가져가면 코드의 가독성과 예측 가능성이 높아집니다.또한 변환 책임을 한 곳에 모으면 관심사 분리 원칙을 지킬 수 있어 관리도 편리해집니다.그래서 이 글에서는 JPA의 @Converter와 유사한 ..

DB 2025.09.02

CaseBuilder 대신 BooleanBuilder를 써야 했던 이유(Feat: querydsl)

들어가면서최근 QueryDSL로 조회 쿼리에서 응답 속도가 비정상적으로 느려지는 문제를 경험했습니다.원인을 추적해보니, 문제의 핵심은 where 절에 사용한 CaseBuilder였습니다.status 컬럼을 기준으로 조건 분기를 작성했는데, 특정 상태값일 때만 조회가 유독 느렸습니다.이후 BooleanBuilder로 로직을 변경한 결과, 쿼리 속도가 수 초에서 수백 밀리초로 개선되었습니다.사용했던 상황비슷한 상황으로 다음과 같은 예제를 만들었습니다.게시글의 상태(status)가 DELETED, PENDING, ACTIVE 등의 값으로 존재하는 게시판 시스템이 있다고 가정해보겠습니다.A 사용자(예: 관리자)는 status = 'PENDING' 상태의 게시글을 그대로 보아야 하고,B 사용자(예: 일반 직원)에..

DB 2025.07.27

Querydsl 다중 where 조건 만들기

들어가면서Querydsl의 장점 중 하나는 쿼리를 Java로 쿼리를 만들 수 있다는 것입니다.그래서 where문에 사용되는 다양한 조건을 메서드화하여 조립하여 만들어 가독성도 높아집니다.특정 조건같은 경우는 다양한 조회에서 사용할 수 있기 때문에 재사용성도 높아집니다.사용방법간단하게 User를 조회할 때 이메일과 이름으로 조회하는 경우로 사용법을 작성하겠습니다.// 메서드화하지 않은 버전 이메일 and 이름 조건 User user = queryFactory.selectFrom(user) .where(user.email.eq("test@test.com") ,user.name.eq("홍길동")) ..

DB 2025.04.23

EXISTS 연산자에 대해서(Feat: querydsl)

들어가면서EXISTS 연산자에 대해서 기본인 조건에 존재하는 것이 있으면 'True' 결과 전달한다는 내용만 알고 어떤 상황에서 사용하는지를 정확하게 몰랐다고 생각됩니다.그냥 INNER JOIN이나 OUTER JOIN을 주로 사용해서 exists를 거의 사용하지 않았습니다.최근 쿼리를 개선하다보니 join이 아닌 exists를 사용하여 속도 개선이 많이 발생한 내용을 공유드립니다.exists는 언제 사용해야할까?위에서 적은 것처럼 존재하면 'True'로 반환하기 떄문에 조건에 따라 데이터를 걸러내어 결과를 조회할 때 사용되고 있습니다.사실 IN 연산자를 이용하여 조회해도 동일한 결과를 얻을 수 있지만 서브쿼리 결과가 100개 이상 나올 가능성이 있으면 IN 연산자를 사용할 수 없습니다.IN 연산자가 SE..

DB 2025.04.13

[JPA] 엔티티 값을 변환하여 저장, 조회하기(Feat: @Converter)

어떤 값을 저장할 때 데이터베이스에 저장할 때 원하는 값으로 저장하고 조회할 때도 원하는 값이나 타입으로 반환할 때 사용합니다.예를 들어 개인정보의 암호화하여 저장해야하거나 Boolen 타입일 때 Y, N 값으로 데이터베이스에 저장하는 등 다양한 경우에 사용될 수 있습니다.AttributeConverter란AttributeConverter 클래스는 프로퍼티의 값을 저장하거나 읽을 때 사용할 수 있는 인터페이스입니다.public interface AttributeConverter { // 엔티티의 데이터를 데이터베이스 컬럼에 저장할 데이터로 변환한다. Y convertToDatabaseColumn(X attribute); // 데이터베이스에서 조회한 컬럼 데이터를 엔티티 데이터로 변환한다...

DB 2025.03.10

ORA-01502: 인덱스 인덱스 이름 또는 인덱스 분할영역은 사용할 수 없는 상태입니다.

Select는 정상적으로 가능한데 Insert를 하는 과정에서 ORA-01502 오류가 발생했습니다.생각해보니 컬럼 중 CLOB 컬럼을 테이블스페이스로 변경하는 작업을 진행하였고 해당 작업으로 인해서 발생한 문제인듯 싶습니다.해당 오류는 DDL 작업 또는 직접로드로 인해 인게스 또는 인덱스 파티션을 엑세스할 수 없다는 오류입니다.(이미지 참조) 인터넷에 검색하는데 대부분 인덱스를 리빌드하여 문제를 해결하는 내용은 있는데 확인하는 과정이 잘 안나와서 찾기 힘들었습니다. SELECT INDEX_NAME, STATUS, OWNER FROM ALL_INDEXESWHERE OWNER = '소유자'AND INDEX_NAME = '인덱스 이름'해당 쿼리를 실행하면 STATUS가 UNUSABLE로 나옵니다. ALTER..

DB 2025.02.18