Spring
14 posts
[QueryDSL] 3. QueryDSL 기본문법 (2)

querydsl의 기본문법 중 조인, 서브쿼리, case문 등에 대해서 알아보자. 1. 조인 기본적으로 jpql의 조인과 같다. 연관관계가 없어도 querydsl에서 join을 할 수 있다. Join on 절 on절을 사용하면 조인할 대상을 줄여준다. 조인 대상 필터링 inner join일 경우는 on을 쓰는 것과 where에 조건을 더하는 것과 동일한 결과를 반환한다. left join일 경우에는 없는 것도 left 부분은 가져오기 때문에 위와 같은 방법을 써주어야 한다. 따라서 outer join이 필요한 경우에만 on필터링을 사용하자. 연관관계가 없는 엔티티 outer join 일반 조인 : leftJoin(member.Team, team) on 조인 : from(member).leftJoin(team).on(…) 2. Fetch 조인 페치조인은 SQL에서 제공하는 기능이 아니고 SQL 조인을 활용해서 연관된 엔티티를 SQL 한번에 조회하는 기능이다. 성능 최적화를 위해 사용…

June 10, 2022
Spring
[QueryDSL] 2. QueryDSL 기본문법 (1)

QueryDSL이 무엇인지와 환경설정하는 방법에 대해 배웠으니 이제 본격적으로 문법을 배워보자. 1. 기본 Q-Type 활용 querydsl 라이브러리가 생성한 Q 클래스를 살펴보면 아래와 같이 static 변수로 클래스에 대한 Q객체를 생성해 둔 것을 확인할 수 있다. 따라서 우리가 querydsl을 사용할 때는 static import로 해당 객체를 불러와서 객체의 멤버 변수인 ‘member’를 사용하면 아래와 같이 간결하게 코드를 짤 수 있다. 그리고 Spring에서 주입해주는 em 은 멀티쓰레드 환경에서 안전하도록 구성되어 있기 때문에 JPAQueryFactory는 동시성 문제를 고려하지 않고 따로 클래스의 필드로 빼서 사용하면 된다. 멀티쓰레드 환경에서 현재 나의 transaction이 어디에 걸려있느냐에 따라 transaction에 바인딩 되도록 em을 분배해주기 때문이다. 2. 검색 조건 쿼리 querydsl은 JPQL이 제공하는 모든 검색조건에 대한 메소드를 제공한…

June 09, 2022
Spring
[QueryDSL] 1. QueryDSL이란? QueryDSL 환경설정

1. QueryDSL이란? QueryDSL은 Java 코드로 쿼리를 짜서 DB에 접근하는 방식이다. 기존 데이터 접근 방식인 jdbcTemplate, Mybatis 와 같은 방법에서는 직접 SQL 쿼리를 짜야만 했다. JPA에서는 Spring data jpa를 통해서 조회 조건이 간단한 쿼리 같은 경우에는 별도의 쿼리를 짜지 않고도 DB로부터 데이터를 불러 올 수 있었다. 그러나 복잡한 조회가 필요할 경우 불가피하게 JPQL을 통해서 아래와 같이 쿼리를 직접 짜야 했다. 그러나 QueryDSL을 사용하면 아래와 같이 자바코드의 형태로 쿼리를 짤 수 있고 여러가지 장점이 있다. 컴파일 타임에서 에러를 잡을 수 있다. 코드 자동 완성의 도움을 받을 수 있다. 동적쿼리를 편하게 짤 수 있도록 도움을 준다. 메소드를 뽑아 낼 수 있어 재사용이 가능하다. parameter 바인딩을 자동으로 해준다. Spring data JPA와 QueryDSL을 함께 활용하면 RDB를 사용한 개발환경에서 …

June 05, 2022
Spring
[JPA] 8. JPA프록시와 지연로딩(Lazy Loading)과 즉시로딩(Eager Loading)

1. JPA에서 프록시란 무엇인가? 1) em.find vs em.getReference em.find를 하게 되면 JPA가 실제 entity 객체를 반환하지만, em.getReference를 하게 되면 DB조회를 미루는 ‘프록시’ entity 객체를 반환한다. 프록시 객체는 실제 Entity 타깃 객체는 가지고 있지 않고, id값만 가지고 있는 비어있는 객체이다. 프록시 객체는 실제 Entity를 상속해서 만들어지며, Hibernate가 내부적으로 만든다. 실제 클래스와 겉 모양이 같기 때문에 사용하는 입장에서는 진짜 객체인지 프록시 객체인지 구분하지 않고 사용할 수 있다. 프록시 객체는 실제 객체의 참조(target)를 보관하고, 프록시 객체를 호출하면 프록시 객체는 실제 객체의 메소드를 호출한다. 이렇게 호출을 한다고 생각해보자. getName 호출하게 되면 MemberProxy객체에 target이 없기 때문에 JPA가 영속성 컨텍스트에 진짜 Member객체 가져오라고 초…

March 24, 2022
Spring
[JPA] 7. 상속관계 매핑 전략 (슈퍼타입, 서브타입)

JPA에서 엔티티 간에 다양한 연관관계를 매핑하는 방법에 대해서 알아보았다. 이제는 조금 더 나아가 단순히 다대다, 다대일만의 관계가 아니라 JPA에서 상속관계를 어떻게 매핑하는 지에 대해서 알아보고자 한다. 그런데 생각해보면 관계형 데이터베이스에는 ‘상속’이라는 개념이 객체지향과는 달리 존재하지 않는다. 그렇지만 이와 유사한 슈퍼타입, 서브타입 모델링 기법이 있는데, JPA에서는 이를 사용해서 객체의 상속관계를 DB의 슈퍼타입/서브타입 관계로 매핑시켜준다. 그리고 관계형 DB에서 슈퍼타입/서브타입 논리 모델링을 물리 모델링하고자 할 때 구현하는 방법은 크게 3가지이며 이 3가지 방식 중 어떤 방식을 선택해도 JPA에서 연관관계 매핑을 지원한다. 1. 조인 전략 앨범 데이터 INSERT시 ITEM, ALBUM 테이블 각각에 데이터를 넣고 조회 시는 ITEM_ID로 ITEM, ALBUM을 조인해서 가져오는 방식이다. 이 때 ITEM 테이블에 어떤 서브타입인지를 구분하는 DTYPE…

March 20, 2022
Spring
[JPA] 6. 다양한 연관관계 매핑

JPA에서 제공하는 다양한 연관관계 매핑하는 방법에 대해서 알아보기에 앞서, 연관관계를 매핑할 때 고려해야 할 요소는 3가지임을 기억하자. 다중성 @ManyToOne -> 제일 많이 사용된다. @OneToMany -> 사용할 수는 있지만 ManyToOne의 양방향으로 커버 가능하다. @OneToOne -> 가끔 @ManyToMany ->실무에서 안 씀 단방향인가 양방향인가 연관관계의 주인이 어느 쪽인가 1. 다대일( ManyToOne ) 다대일 관계는 가장 많이 사용되는 관계이다. 사실 상 거의 이것으로만 설계할 수 있다. 다대일 관계의 특징은 FK를 ‘다’ 쪽에서 관리하는 것이고, 연관관계의 주인도 ‘다’ 쪽이라는 것이다. 1. 단방향 2. 양방향 설계는 다대일 단방향에서 끝났지만 만약에 Team 에서도 Member에 대한 조회를 하고 싶다면 OneToMany를 ‘일’ 쪽인 Team에 추가하여 매핑해주면 된다. 연관관계의 주인은 Member이므로 조회만 된다는 점에 유의하자. …

March 16, 2022
Spring
[JPA] 5. 연관관계 매핑 (feat. 연관관계의 주인)

JPA 연관관계 매핑을 배우기에 앞서, 객체와 테이블의 연관관계를 맺는 방법이 다르다는 것을 이해해야 한다. JPA 1. 에서 언급했듯이, 객체는 참조를 통해, 테이블은 FK를 통한 조인으로 연관관계를 맺는다. 회원과 팀이 다대일 관계일 때 객체를 테이블에 맞추어 모델링 한다면 아래와 같을 것이다. 그리고 이렇게 Entity 상에서 이렇게 매핑을 하게 되면 서로 연관된 데이터를 가져오고 싶을 때 이렇게 Id를 통해서만 가져올 수 있게 된다. 그리고 이것은 객체지향스럽지 않은 방식이다. JPA에서는(ORM에선) 이를 어떻게 모델링 할 수 있을까? JPA에서는 단방향, 양방향 연관관계를 통해 객체지향적으로 프로그래밍이 가능하도록 해준다. 1. 단방향 연관관계 Entity 클래스에서 참고하고자 하는 다른 Entity 클래스의 참조형을 멤버변수로 선언하는데, 이 때 참조형으로 생성하는 Entity는 FK를 가지고 있지 않은 쪽 ( ‘Many’ 인 쪽 ) 이다. 즉 Team과 Membe…

March 12, 2022
Spring
[JPA] 4. 엔티티(Entity) 매핑 기초

JPA의 내부동작, 즉 영속성 컨텍스트의 정의, 장점, 라이프사이클 등에 대해서 이전 글을 통해 알아 봤다면, 이제 Entity 매핑을 실제로 어떻게 하는 지를 알아보자. 1. 객체와 테이블 맵핑 ( @Entity, @Table ) @Entity가 붙은 클래스는 JPA가 관리하게 된다. Entity 작성 시 주의사항 기본 생성자는 필수이다. final, enum, interface, inner 클래스 사용 X 저장할 필드에 final 사용 X @Table은 엔티티와 맵핑할 테이블 지정 가능 2. DB 스키마 자동 생성 JPA에서는 DDL을 앱 실행 시점에 자동 생성해준다. ( 운영 환경에서는 사용하면 안됨 ) : JPA가 테이블 중심이 아닌 객체 중심임을 보여준다. persistence.xml에서 아래와 같이 옵션이 설정되어 있어야 한다. 여기서 value값에 옵션을 지정해주는데 옵션의 종류는 아래와 같다. create : 기존테이블 삭제 후 다시 생성(DROP + CREATE)…

March 08, 2022
Spring
[JPA] 3. JPA 내부동장 방식 : 영속성 관리

지난 글에서는 JPA 프로그래밍시, EntityManager를 생성하여 persist, set 등의 CRUD 작업을 수행하는 것을 알아보았다. 지난 글에선 설명하지 않았지만 EntityManager가 데이터를 persist 하게 되면 데이터는 ‘영속성 컨텍스트’에 저장되게 된다. JPA에서 가장 중요한 것은 객체와 관계형 DB의 맵핑 문제, 그리고 영속성 컨텍스트이다. 영속성 컨텍스트란? 영속성 컨텍스트를 이해하기에 앞서, EntityManager(이하 EM)와 EntityManagerFactory(이하 EMF)가 동작하는 방식에 대해서 먼저 이해해야 한다. EMF는 고객의 요청이 올 때 마다 EM을 생성하고 EM은 내부적으로 DB 커넥션을 사용해서 DB를 사용한며, 이를 도식화하면 아래와 같다. 그렇다면 영속성 컨텍스트란 무엇인가? “Entity를 영구 저장하는 환경”이라는 뜻이다. 영속성 컨텍스트는 논리적인 개념이며 또한 EM과 1대1로 대응하고, EM을 통해 접근/관리 한다…

February 27, 2022
Spring
[JPA] 2. JPA 구동방식과 JPQL의 개념

JPA 구동 방식 JPA는 아래와 같은 방식을 통해 동작한다. EntityMangerFactory는 하나만 사용해서 앱 전체에서 공유해서 사용하며 EntityManager는 thread간에 공유해서는 안된다. 그리고 JPA의 모든 데이터 변경은 트랜잭션 안에서 실행해야 한다. ​ 순수 JPA만 설정했을 때 어떤 식으로 프로그래밍을 하게 되는 지 아래 코드를 통해서 살펴보자. EntityManagerFactory를 생성하고, 이를 통해 EntityManager도 생성한다. JPA의 모든 데이터 변경은 트랜잭션 안에서 실행되야 하기 때문에 EntityTransaction 객체를 생성하여 tranasaction의 begin, end를 관리해주어야 한다. ​ 아래 코드에서 순수 Jpa 프로그래밍을 어떻게 하는 지 알 수 있다. 특히 jpa에서 제공하는 수정 기능을 보면 jpa를 사용하면 정말 객체지향적으로 프로그래밍할 수 있음을 알 수 있다. setName 메소드를 통해서 Entity…

February 25, 2022
Spring
[JPA] 1. SQL 중심적 개발의 문제와 JPA

오늘 날 DB를 사용한다고 할 때 아직까지 대부분은 NoSQL보다는 RDB라고 불리는 관계형 데이터베이스를 사용한다. 즉, 개발자는 프로그래밍을 할 때 객체를 DB에 저장하는 작업, 반대로 DB를 객체로 불러오는 작업을 반복해야 만 했다. 개발자가 사실 상 SQL mapper 역할을 했어야만 했다는 것을 말한다. 실제 국내에서는 수 많은 개발업체들과 SI업계에서는 여전히 Mybatis를 사용하며 SQL에 대부분의 비즈니스 로직이 녹아 있다. 그렇다면 이러한 SQL 중심적 개발에는 어떤 문제가 있을까? 쉽게 생각할 수 있는 것은 SQL을 직접 짜는 것이 매우 귀찮은 반복적 작업이라는 것. 예컨대 필드가 추가 되면 INSERT, UPDATE, SELECT등 모든 SQL에 해당 필드가 들어가야 하는 곳을 찾아서 추가해주어야 할 것이다. 그러나 무엇보다도 RDB(관계형 데이터베이스)와 OOP(객체지향 프로그래밍)의 패러다임 불일치에서 오는 문제들이다. 패러다임의 불일치 관계형 DB가 나온…

February 24, 2022
Spring
Spring Swagger 사용하여 API 문서 자동화하기

Spring boot를 사용해서 사이드 프로젝트를 하던 중에 다른 개발자들과의 협업을 위해 API를 문서화시키는 것에 대한 필요성이 있었는데 Swagger를 사용하여 별도의 문서 작성없이 소스상의 간단한 설정을 통해 API 문서 자동화를 구현했다. API 문서 자동화 방법은 아주 간단한데, Gradle의 경우 아래를 build.gradle의 dependenceis에 추가해주면 된다. Maven의 경우 아래를 pom.xml에 dependency에 추가해주면 된다. 이렇게만 하면 되는데, Spring boot 2.6 버전을 쓰는경우에는 NPE가 발생할 수 있다. Spring에서 디폴트로 PathPattern-based matching을 사용하는데, Springfox에서는 Ant-based path matcher가 사용되는 것으로 가정하고 있기 때문에 문제가 발생한다고 한다(https://stackoverflow.com/questions/70036953/springboot-2-6-0-…

February 19, 2022
Spring
[Spring] Spring boot는 무엇을 해주는가? 스프링 부트를 쓰는 이유

Spring을 이용해서 개발을 시작한다고 할 때 대부분의 개발자들은 Spring boot를 이용할 것이다. Spring boot를 활용하게 되면 Spring 사용 시 필요한 여러가지 귀찮은 configuration들을 자동으로 설정해줄 뿐만 아니라 개발자비즈니스 로직 개발에 집중할 수 있도록 여러가지 기능을 제공한다. Spring boot란 무엇인가? 간략하게 정의하면 Spring boot는 Spring framework 을 더 쉽게 사용할 수 있게 해주는 framework로 보면 된다. Spring은 사용하기 위해 필요한 설정 들이 생각보다 복잡한데, Spring boot는 기본적으로 이러한 설정들을 모두 제공하기 때문에, 개발자 입장에서는 초기 개발 환경을 셋팅하는 것이 매우 용이해진다. Spring boot 공식 문서는 다음과 같이 말한다. Spring Boot makes it easy to create stand-alone, production-grade Spring ba…

February 02, 2022
Spring
[Spring] Autowired가 아닌 생성자 주입을 사용해야 하는 이유

Spring에서 의존관계 주입(Dependency Injection)을 할 때 @Autowired를 사용하여 주입하는 경우가 많은데, 스프링에서는 아래와 같이 그렇게 하지 말 것을 권고한다. Field injection is not recommended … Always use constructor based dependency injection in your beans DI를 하는 이유는 객체 내부에서 객체를 직접 생성하는 방식 보다 런타임 시 외부에서 생성한 객체를 인터페이스를 통해 넘겨받는 것이 더 느슨한 결합 방식이기 때문이다. DI 방법 3가지 1. Setter based injection (수정자 주입) 위와 같이 Setter를 통해 주입하는 방식의 경우 Controller 객체가 생성될 때 반드시 service가 초기화 되지 않아도 되기 때문에, NPE 발생 가능성이 존재한다. 그리고 생성자 주입과 필드 주입 방식은 ‘객체가 생성되는 시점’에서 순환 참조가 되는 지 여부…

January 28, 2022
Spring