JPA에는 엔티티 타입(@Entity로 정의하는 객체)과 값 타입(자바 객체나 primitive type)이 존재한다. 엔티티 타입은 데이터가 변해도 식별자로 추적할 수 있다(엔티티의 값을 변경한다고 해도 식별자를 이용해서 인식할 수 있다). 반대로 값 타입은 단순히 값으로서 사용하는 것으로서 jpa에서 추적하지 않는다. 아래에서는 여러가지 종류의 값 타입에 대해서 알아보겠다. 1. 기본값 타입 - Primitive type - 래퍼 클래스 - String 기본값 타입은 생명주기를 엔티티에 의존한다. 값 타입을 엔티티끼리 공유하게 되면 문제가 발생할 수 있으므로 같은 참조값을 가지면 안된다. (물론 자바의 primitive type같은 경우는 당연히 reference를 공유할 수 조차 없어 안전하다.) ..
프록시(Proxy)란? 프록시란, 간단하게 말해 누군가를 대신하여 권한을 받아 수행하는 주체를 말한다. 해당 글에서는 JPA에서 사용되는 프록시 객체에 대한 이야기를 하겠다. 프록시 클래스는 실제 클래스(엔티티)를 상속받아 만들어진다. 따라서 비즈니스 로직에서는 이것이 프록시 객체인지, 실제 엔티티인지 구분없이 사용 가능하다. JPA에서 프록시 패턴의 사용 비지니스 로직이 실행될 때, 어떤 엔티티 객체를 조회하는데 그 엔티티와 관계를 맺고 잇는 다른 엔티티들의 조회도 함께 이루어져야 할 때가 있다. 그런데 그 중에서 한 개의 엔티티만 조회가 이루어져도 상관이 없는 상황에서는 성능상의 손해가 발생할 것이다. 이러한 성능 저하가 발생하지 않게 하기 위하여 '실제 사용되는 시점'에 DB에서 조회하도록..
상속관계 매핑 객체와 달리 RDB에는 상속관계가 존재하지 않는다. 그래서 DB에서는 슈퍼타입-서브타입 관계라는 모델링 기법을 이용해서 객체의 상속관계를 나타낸다. 코드상에서 상속관계 설정은 부모클래스에 @Inheritance 어노테이션을 추가함으로서 설정 가능하다. 1. 부모테이블과 자식테이블을 JOIN하여 연관관계를 맺는다. 2. 부모, 자식 모두를 한개의 테이블로 합치고 TYPE정보를 통해 구분한다. 3. 자식테이블만 만들고 부모테이블의 필드를 포함시켜준다. 1. JOIN을 통한 연관관계 매핑 : @Inheritance(strategy = InheritanceType.JOINED) 부모, 자식객체 각자의 데이터를 저장하는 대신, 자식객체의 테이블에 부모객체의 id를 fk로 두고 관리한다. 이때 jpa..
0. 설계시 생각할것 - 다중성 - 단방향, 양방향 - 연관관계 주인 사실 테이블에서는 외래키 하나로 양쪽 join이 가능하기 때문에 방향성이 의미를 갖지는 않는다. 반면 객체는 참조용 필드가 존재하는 쪽에서만 참조가 가능하기때문에, 한쪽만 참조하면 단방향, 양쪽이 서로 참조하면 양방향 연관관계를 가진다. 그래서 저번 포스트에서 언급했듯이, 테이블과 연관된 단방향 연관관계를 가지는 객체들을 설계한 뒤 양방향 연관관계가 필요하다면 연관관계의 주인을 정하고, 추가적인 메소드를 작성해주면 된다. 따라서 아래에는 기본이 되는 단방향 매핑만 정리하도록 하겠다. 또한(당연한 얘기이지만) 객체 상호간에는 대칭관계를 갖는다 (한쪽이 다대일이면 반대쪽은 일대다). 1. 다대일([N:1]) DB와 매핑하기 - @ManyT..
0. 연관관계 매핑하기 앞에서 배웠던 내용들을 바탕으로 이번에는 쇼핑몰을 만드는 코드를 작성해보자. 회원이 상품을 주문하는 단순한 기능을 구현하기 위해서 다음과 같이 테이블을 설계하였다. 테이블의 구조를 설계했으면 JPA 구성을 위해 엔티티를 설계하고 매핑해보자. 한개의 Member객체는 여러개의 Order를 만들 수 있고(일대다 매핑), Order와 Item사이에는 다대다 매핑이 가능하도록 설계했다(하나의 order에 여러개의 item이 들어갈수도, 한 item이 여러 order에 들어갈수도 있으므로). 그런데 이렇게 객체의 설계를 테이블 구조에 맞춰서 설계하면, 테이블의 fk를 객체에 그대로 가져오게 되고, Order객체에서 객체를 주문한 객체를 찾고싶다면 memberId를 통해서 Member객체의 ..
엔티티에 식별자를 할당하는 데에는 4가지 방법이 있는데, 그 중에 SEQUENCE 전략이 있다. @GeneratedValue(strategy = GenerationType.IDENTITY) : DB에 위임하면 알아서 auto_increment해줌 @GeneratedValue(strategy = GenerationType.SEQUENCE) : DB sequence object 사용 @GeneratedValue(strategy = GenerationType.TABLE) : 키생성 전용 테이블 만들기 @GeneratedValue(strategy = GenerationType.AUTO) : 위의 세가지 전략중 적절하게 지정 SEQUENCE전략 사용 설정 @SequenceGenerator 에노테이션은 시퀀스 생성..
설계적인 측면 (객체와 관계형 데이터베이스를 어떻게 매핑해서 사용하는지)에 관한 공부 객체와 테이블 매핑 - @Entity : JPA가 관리하는 객체 명시 - 클래스와 테이블을 매핑하기 위하여 클래스에 @Entity를 명시해준다. @Entity가 명시되지 않은 클래스는 JPA가 관리대상으로 생각하지 않기 때문에 JPA를 사용해서 테이블과 매핑하려면 @Entity 어노테이션을 반드시 명시해주어야 한다. - 기본(public/protected) 생성자가 필수적으로 요구된다. - DB에 저장할 필드에 final 사용이 불가능하다. - @Table : 엔티티와 매핑할 테이블 지정 - @Table(name = " ")와 같이 매핑할 테이블의 이름을 변경할 수 있다. 데이터베이스 스키마 자동 생성이란? JPA는 애..
개요 - DB와 객체를 어떻게 설계하여 매핑(Mapping)할 것인가? - 내부에서 JPA는 어떻게 동작할까? 어플리케이션의 개발시 하나의 EntityManagerFactory를 통해서 고객의 요청(트랜잭션)이 올때마다 EntityManager가 생성되고 커넥션을 통해서 DB와 상호작용이 이루어진다. 이때 EntityManager마다 1대1로 영속성 컨텍스트가 생성된다. 영속성 컨텍스트란? 엔티티를 영구 저장하는 환경이라는 의미 애플리케이션과 데이터베이스 사이에서 객체를 임시 보관하는 가상의 캐시, 데이터베이스같은 역할을 한다. 엔티티매니저를 통해서 엔티티를 저장/조회!!하면 엔티티매니저는 영속성 컨텍스트를 통해서 엔티티를 보관하고 관리한다. >> 저장 뿐 아니라 조회시에도 DB의 데이터는 영속성 컨텍스..
JPA를 쓸때 EntityManager.find()와같은 간단한 함수로 실행할 수 없는 요청은 ... EntityManager em = emf.createEntityManager(); ... // createQuery메소드를 통해서 쿼리를 짤수있다. List result = em.createQuery("select m from Member as m", Member.class).getResultList(); 위와 같이 쿼리를 직접 입력 가능하다. 다만, 데이터베이스 테이블을 대상으로 쿼리를 짜는 SQL과 달리, JPQL은 엔티티 객체를 대상으로 쿼리문을 작성한다. 그러면 jpa가 자동으로 코드를 바꿔서 호출해준다.
설정 JPA 실습을 위해서 실습용 DB를 설치하고, 프로젝트의 pom.xml에 라이브러리를 추가해준다. spring.io사이트에 들어가서 확인해보면 실습을 진행할 스프링부트 2.6.2버전에서는 hibernate 5.6.3.Final을 사용함을 알 수 있다. 여기서 하이버네이트란 JPA의 구현체로, JPA '인터페이스'를 구현한다. JPA는 단순히 hibernate를 추상화한 인터페이스일뿐, JPA자체로만 동작하지 않는다. 따라서 스프링부트와 호환되는 hibernate버전을 의존관계에 추가해주자) //pom.xml 일부 org.hibernate hibernate-core 5.6.3.Final //스프링부트 버전에 맞춘 하이버네이트 버전 ... com.h2database h2 2.0.204 //사용중인 h2..
JPA (Java Persistance API) 과거에는 객체를 DB에 저장하기 위하여 Jdbc를 일일히 입력해야 했다. 그 후에 JdpcTemplate이 나오면서 보다 번거로움은 줄었지만 sql은 직접 개발자가 String으로 입력해주어야 하고, 동적쿼리 문제를 해결하는데 어려움을 겪었다. 나 또한 올해 말에 진행했던 앱 프로젝트에서 DB연동을 위해 sql을 일일히 함수에 추가해주고, 계획에 변경이 생길 때마다 관련 sql문과 함수들을 찾아 직접 변경해주며 번거로움을 느낀 경험이 있었다. 하지만 번거롭더라도 관계형 데이터베이스(RDB)를 다루기 위해서는 sql은 필수적이기 때문에 생략할 수 없다. 그래서 CRUD 등의 기능을 구현하기 위해서는 객체를 생성하고 나서 sql문에 의존적인 개발이 진행될 ..