Programming-[Backend]/JPA 34

[TIL] JPA @ManyToMany 적용, 테이블 이름과 컬럼, 저장 처리 방식

1. 배경 예전에 JPA를 학습할 때, @ManyToMany는 사용하면 안된다고 배웠었다. 이것은 혹시나 나중에 두 엔티티간 매핑 테이블에 컬럼이 추가될 수도 있는데 @ManyToMany를 적용하면 컬럼 추가가 어렵기 때문이라고 배웠다. https://whitepro.tistory.com/413 그래서 한 번도 써보지 않았는데, 정말 순수하게 mapping만 필요한 경우이고 간단하게만 적용하면 되는 경우라 적용하게 되었다. 위 예시에서처럼 추가 정보가 필요한 경우 두 엔티티 중 하나의 테이블에 컬럼을 추가하면 된다고 생각이 들었다. 그리고 서비스가 크지 않고 향후에도 큰 영향도가 없다고 판단되어 일단 적용해보았다. 절대 권장할만한 방식은 아닌 것 같다. 그래도 일단 기록은 남긴다. 2. 실제 적용 예시 ..

[링크] could not initialize proxy - no Session

Service 레이어에서 Entity를 가져올 때 발생할 수 있다. Entity에 접근해서 JPA의 Fetch 설정이 LazyLoading(주로 1:N으로 연결된 필드) 설정인 경우 서비스 레이어 -> 컨트롤러 레이어에서 프록시 객체를 넘겨서 발생할 수 있다. 아래 참조 글에 따르면 이것은 프록시 객체를 가져오는 것도 트랜잭션 단위로 이루어지기 때문이다. 서비스 레이어에서는 StudentDto내에 School 엔티티를 프록시로 들고 있어도 되지만, 그대로 서비스 레이어를 끝내고 다른 레이어로 넘어가면 세션이 끝나버려서 프록시로 들고 있던 School 엔티티의 값을 참조하지 못하게 된다. 서비스 레이어에서 모든 프록시 객체들을 개별 DTO로 변환하는 것이 추천된다. Eager 로딩할 수도 있겠으나 N+1 ..

[TIL] JPA Expressions Date 오늘 날짜 또는 상수 값 넣기 : dateTemplate, SQL function(내장함수)

목표 JPA의 select 구문에 내장함수(SQL function)이나 상수값을 넣는다. 코드 다음과 같이 넣어주면 된다. return jpaQueryFactory .select(Projections.constructor(XXXDto.class, Expressions.as(Expressions.dateTemplate(Date.class, "function('current_date')"), "약어"), Expressions.as(Expressions.asNumber(0).intValue(), "약어"), Expressions.as(Expressions.asString("-"), "약어"), ... 중략 해석 & 배울점 1. Select 구문에는 Expressions로 내장함수, 상수값을 적을 수 있고, E..

[링크] JPA Map 결과 리턴(결과 집합 그루핑)

JPA에서 결과를 Map형태로 추출하고 싶을때는, transform 메서드와 GroupBy.groupBy 인터페이스를 활용하면 된다. 3.2.4. 결과 집합(aggregation) com.mysema.query.group.GroupBy 클래스는 메모리에서 쿼리 결과에 대한 집합 연산을 수행하는 집합 함수를 제공한다. 다음은 사용 예이다. 부모 자식 관계에 대한 집합 연산 import static com.mysema.query.group.GroupBy.*; Map results = query.from(post, comment) .where(comment.post.id.eq(post.id)) .transform(groupBy(post.id).as(list(comment))); 이 코드는 post id와 관련..

[TIL][에러] SQL-Server - hibernate; JPA 적용 Sort, Paging 시 데이터 누락, 중복 문제

현상 SQLServer - JPA 조합으로 paging을 통해 데이터들을 list 형태로 불러오는 과정에서 특정 조건으로 Sorting을 하면 데이터의 중복이나 누락이 발생했다. 예를 들어 아래 사진과 같은 상황에서 Code-asc 조건으로 sorting을 하면 page 6의 가장 마지막 데이터와 page 7의 가장 처음 데이터가 중복되었다. 그리고 Sorting을 하지 않았을때와 했을 때 누락되는 데이터가 있었다. 원인과 해결책 해결책 hibernate에서 참조로 하는 SQLServerDialect를 SQLServer2012Dialect로 변경해준다. from import org.hibernate.dialect.SQLServerDialect; to import org.hibernate.dialect.S..

[Querydsl][작성중] 6. 실무 활용 - 사용자 정의 Repository

1. 사용자 정의 Repository Spring Data Jpa 등에서 제공하지 않는 querydsl을 적용한 sql문 작성을 위해서는 사용자 정의 레포지토리가 필요하다. 강의 자료에 따르면 다음과 같이 구성하면 된다. 이 방식은 기존에 작성해둔 MemberRepository interface 를 계속 사용하겠다는 의미가 된다. 코드로 보면 아래와 같다. MemberRepositoryCustom 1 2 3 public interface MemberRepositoryCustom { List search(MemberSearchCondition condition); } Colored by Color Scripter cs Custom 인터페이스를 상속받는 구현체인 MemberRepositoryImpl.clas..

[Querydsl] 5. 중급 문법 - 벌크연산, SQL function, 동적 검색 적용 API 개발해보기

1. 벌크연산 JPA 기본에서 JPQL문의 createQuery 뒤에 .executeUpdate() 구문을 넣어주면 벌크 연산이 가능하다고 배웠었다. 벌크 연산 후 em.flush, em.clear를 실행하거나 spring data jpa에서는 @Modifying을 적용해서 영속성 컨텍스트가 동기화되도록 만들어줘야 한다는 것도 배웠다. (https://whitepro.tistory.com/439) querydsl에서는 .execute()를 넣어주면 된다. 1 2 3 4 5 6 7 8 9 10 11 12 @Test public void bulkUpdate() { //28살 이하의 member1, member2의 이름이 "비회원"으로 변경 long count = jpaQueryFactory .update(m..

[Querydsl] 4. 중급 문법 - Projections, BooleanBuilder

1. 특정 DTO로 원하는 필드값만 가져오기 복습겸 JPQL로 원하는 필드값만 가져오는 것을 연습한다. MemberDto를 만들고 member.username, member.age 값을 가져와본다. 순수 JPA에서 JPQL로 Dto 조회 select 절에 new Operator를 사용해서 MemberDto를 가져올 수 있도록 작성한다. 특이한 점은 해당 Dto가 있는 패키지 위치를 전부 작성해야된다는 점이고, 타입은 MemberDto.class로 가져오면서도 from절은 Member 엔티티로 지정하고, MemberDto의 필드값도 이 엔티티 기반으로 m.username, m.age 로 작성해준다는 점이다. MemberDto.class 생성자가 반드시 있어야 한다. 1 2 3 4 5 6 7 @Data @A..

[Querydsl]3. 기본 문법 - 서브쿼리, Case, 상수 문자 더하기

1. 서브쿼리 서브 쿼리의 필요성과 SQL 사용 권장 사항 서브쿼리를 사용하면 SQL의 결과를 한 번에 깔끔하게 가져올 수 있다. 그러나 SQL로 모든 데이터를 한번에 가져오고, 깔끔하게 정리까지 할려는 것은 과한 측면이 있다. SQL문 하나에 모든 데이터를 가져오도록 하지말고, 작은 SQL문으로 쪼개어 애플리케이션이나 화면단에서 데이터를 합치자. 너무 방대한 쿼리문을 작성하는 것보다 여러 개의 의미있는 SQL문을 작성하는 것이 재사용성과 가독성을 높이는데 도움을 줄 수 있다. 다만, 성능이 매우 중요하고 실시간으로 데이터를 빠르게 받아와야 하는 경우에는 쿼리 횟수를 줄여서 성능을 확보하는 것이 중요할 수도 있다. raw 데이터를 가져오는 방식으로 SQL문을 작성해야한다. SQL문에서 제공하는 기본적인 ..

[Querydsl]2. 기본 문법

기본문법은 대부분 익숙한 내용이라, 몰랐던 부분이나 중요한 부분만 위주로 개조식으로 작성한다. Q객체 생성하기 Maven으로 Build를 하면 Q 객체를 생성해줬었는데, Gradle은 Build를 해도 Q객체를 생성하지 않는다. 이전 글에서 배운 것처럼 compileQuerydsl을 직접해줘서 Q객체를 생성해줘야 한다. 기본 문법 static import를 안해서 어색할 수 있다. Q객체의 alias를 "m"과 같이 설정하고, 해당 객체를 querydsl 문법으로 넘기는 방식을 적용함을 자각하고 있자. 이 alias는 querydsl이 JPQL을 작성할 때 sql문의 alias로 사용한다. 같은 Q객체를 동시에 조회해야할 때, Q 객체의 alias를 지정해서 사용해주면 된다! 똑같은 엔티티에서 다른 내용..