본문 바로가기

Backend

(49)
JPQL의 소개와 기본 문법 JPQL JPQL은 Java Persistence Query Language의 약자로, JPA가 지원하는 객체지향 쿼리 언어이다. ORM을 사용하면 데이터베이스 테이블이 아닌 엔티티 객체를 대상으로 개발하므로 검색도 테이블이 아닌 엔티티 객체를 대상으로 하는 방법이 필요하다. JPQL은 이런 문제를 해결하기 위해 만들어졌다. JPQL의 특징은 다음과 같다. SQL이 데이터베이스 테이블을 대상으로 하는 데이터 중심의 쿼리라면, JPQL은 객체를 대상으로 하는 객체지향 쿼리이다. SQL을 추상화해서 특정 데이터베이스 SQL에 의존하지 않는다. JPQL은 결국 SQL로 변환된다. JPQL을 사용하면 JPA는 이 JPQL을 분석한 다음 적절한 SQL을 만들어 데이터베이스를 조회한다. 그리고 조회한 결과로 엔티티..
HttpMessageConverter, ArgumentResolver, MappingJackson2HttpMessageConverter(JSON을 이용한 @RequestBody/@ResponseBody의 동작 원리) @RequestBody는 클라이언트 측에서 보낸 HTTP 요청 메시지 바디의 데이터를 자바 객체로 변환해준다. 그리고 @ResponseBody는 객체 반환시 객체가 JSON 형태로 변환되어 응답이 나가도록 해준다. 이들의 동작 원리를 이해하기 위해서는 직렬화/역직렬화의 개념과 스프링 MVC에서 제공하는 HttpMessageConverter에 대해 알아야 한다. 직렬화/역직렬화 직렬화(Serialization)는 객체를 문자열 또는 바이트 스트림으로 변환하는 것을 의미한다. 반대로 역직렬화(Deserialization)는 문자열 또는 바이트 스트림을 다시 객체로 변환하는 것을 의미한다. 즉 @RequestBody는 클라이언트 측에서 보낸 HTTP 요청 메시지 바디의 데이터를 자바 객체로 변환하는 역직렬화..
영속성 전이(cascade)와 고아 객체 영속성 전이(cascade) 특정 엔티티를 영속 상태로 만들 때 연관된 엔티티도 함께 영속 상태로 만들고 싶으면 영속성 전이 기능을 사용하면 된다. 예를 들어 엔티티를 저장하거나 삭제할 때 연관된 엔티티도 함께 저장하거나 삭제하는 경우이다. JPA는 cascade 옵션으로 영속성 전이를 제공한다. public enum CascadeType { ALL, // 모두 적용 PERSIST, // 양속 MERGE, // 병힙 REMOVE, // 삭제 REFRESH, // REFRESF DETACH // DETACH } cascade 옵션 적용 전 예를 들어 다음과 같이 부모와 자식이 일대다 관계로 정의되어 있다고 하자. @Entity public class Parent { @Id @GeneratedValue pr..
프록시와 지연 로딩 프록시가 필요한 이유 다음 예제는 회원 엔티티를 찾아서 회원과 팀의 이름을 출력한다. Member member = em.find(Member.class, memberId); Team team = member.getTeam(); System.out.println("회원 이름: " + member.getName()); System.out.println("팀 이름: " + team.getName()); 반면 다음 예제는 회원 엔티티를 찾아서 회원의 이름만 출력하고, 회원과 관련된 팀 엔티티는 전혀 사용하지 않는다. Member member = em.find(Member.class, memberId); Team team = member.getTeam(); System.out.println("회원 이름: " + ..
양방향 연관관계 매핑 객체와 테이블의 차이 객체의 양방향 연관관계: 정확히 말하자면 객체에는 양방향 연관관계가 없다. 서로 다른 단방향 연관관계 2개가 양방향처럼 보일 뿐이다. 회원 -> 팀 팀 -> 회원 테이블의 양방향 연관관계: 반면 데이터베이스 테이블은 외래 키 하나로 양쪽에서 서로 조인할 수 있다. 즉 외래 키 하나로 두 테이블은 양방향 연관관계를 맺는다. 회원 팀 테이블은 외래 키 하나로 두 테이블의 연관관계를 관리한다. 따라서 엔티티를 단방향으로 매핑하면(단방향 연관관계), 참조를 하나만 사용하므로 이 참조로 외래 키를 관리하면 된다. 그런데 엔티티를 양방향으로 매핑하면(양방향 연관관계), '회원 -> 팀', '팀 -> 회원' 두 곳에서 서로를 참조한다. 즉 테이블의 외래 키는 하나인데, 객체에서 연관관계를 관리하..
기본 키 매핑 JPA의 기본 키 매핑 JPA는 엔티티들을 영속성 컨텍스트에서 관리하는데, 영속성 컨텍스트에서 관리되려면 엔티티를 구분할 수 있는 식별자가 반드시 필요하다. 식별자가 되는 필드는 엔티티 클래스에서 @Id 어노테이션을 통해 지정할 수 있다. JPA가 제공하는 기본 키 생성 전략은 다음과 같다. 직접 할당: 기본 키를 애플리케이션에서 직접 할당한다. 자동 생성 IDENTITY: 기본 키 생성을 데이터베이스에 위임한다. SEQUENCE: 데이터베이스 시퀀스를 사용해서 기본 키를 할당한다. TABLE: 키 생성 테이블을 사용한다. 자동 생성 전략이 이렇게 다양한 이유는 데이터베이스 벤더마다 지원하는 방식이 다르기 때문이다. 예를 들어 오라클은 시퀀스를 제공하지만 MySQL은 시퀀스를 제공하지 않고 그 대신에 기..
엔티티 매니저와 영속성 컨텍스트 엔티티 매니저 팩토리(entity manager factory), 엔티티 매니저(entity manager) 엔티티 매니저는 엔티티를 저장, 수정, 삭제, 조회하는 등 엔티티와 관련된 모든 일을 처리한다. 이름 그대로 엔티티를 관리하는 관리자이다. 엔티티 매니저 팩토리는 이름 그대로 엔티티 매니저를 만드는 공장인데, 엔티티 매니저 팩토리를 생성하는 비용은 매우 크다. 따라서 한 개만 생성해서 애플리케이션 전체에서 공유하도록 설계되어 있다. 반면, 공장에서 엔티티 매니저를 생성하는 비용은 거의 들지 않는다. 그리고 엔티티 매니저 팩토리는 여러 스레드가 동시에 접근해도 안전하므로 서로 다른 스레드 간에 공유해도 되지만, 엔티티 매니저는 여러 스레드가 동시에 접근하면 동시성 문제가 발생하므로 스레드 간에 절대..
서블릿의 예외 처리, 스프링의 예외 처리(HandlerExceptionResolver) 서블릿의 예외 처리 서블릿의 예외 처리 흐름 먼저 스프링이 아닌 순수 서블릿 컨테이너는 어떻게 예외 처리를 하는지 알아보자. 서블릿은 다음 2가지 방식의 예외 처리를 지원한다. Exception 순수 자바 프로그램의 경우, 자바의 main 메서드를 직접 실행하면 main이라는 이름의 스레드가 실행된다. 그리고 실행 도중에 발생한 예외를 잡아서 처리하지 않으면 처음에 실행한 main 메서드까지 예외가 넘어가고, 예외 정보를 남기며 해당 스레드는 종료된다. 반면, 웹 애플리케이션은 사용자 요청별로 별도의 스레드가 할당되고 서블릿 컨테이너 안에서 실행된다. 만약 컨트롤러에서 예외가 발생했는데 이를 잡지 못하면 어떻게 될까? 예외 발생시 흐름은 다음과 같다. WAS(여기까지 예외 전파) ⬅️ 필터 ⬅️ 서블릿 ..