JPA20 16. [JPA] Bulk Insert 한번에 대량의 데이터를 저장해야 하는 경우가 있을 것이다.예를 들어 엑셀 업로드 하면 해당 데이터들을 DB에 저장해야 한다.데이터가 3만 건 존재한다고 했을 때 어떻게 처리 해야 할 것인가? 먼저 주의점에 대해서 나열해보자.3만 건의 데이터를 영속화 한 뒤 flush 하는 방법은 과연 괜찮을까? 메모리가 충분하다면 3만 건 데이터는 문제 없이 처리될 것이다. 다만, 그 이상의 데이터를 영속화 하게 된다면 out of memory 예외를 만나게 된다.많은 데이터를 영속화해서 flush 하면 메모리 오류가 나니~ 건건이 영속화하고 flush 하면 되겠네? 라고 생각하면 이 또한 큰 오산이다. 처리 속도도 오래 걸릴 뿐더러 데이터 양만큼의 통신이 발생하기 때문에 비효율적이다.그럼 방법이 뭔데?의외로 해답은 단.. 2017. 12. 14. 15. [JPA] Spring Data JPA Spring Data 프로젝트 하위에 Spring Data JPA가 존재JPA를 쉽게 사용할 수 있도록 제공해 주는 프로젝트이다. "쉽게 사용할 수 있다" 의미?대게 DB관련 로직이 있는 데이터 계층에 select, insert, update, delete와 같은 코드를 반복적으로 작성한다.Spring Data JPA에서는 이런 지루하고 반복적인 작업을 인터페이스 선언만으로 해결하였다. JpaRepository 인터페이스를 상속하면 된다. 인터페이스만 선언해서 어떻게 해결했지? 라는 의문점이 들 수 있을 것이다. Spring Data JPA에서는 런타임 시점에 구현 객체를 동적으로 생성해준다. (JDK Dynamic Proxy 이용)12public interface SDTRepository extends.. 2017. 12. 14. 20. [JPA] lombok 사용 시 주의사항 엔티티 클래스에 lombok을 사용하면 StackOverflowError 오류가 발생할 수 있다. 다음과 같은 엔티티 연관 관계가 있다고 하자.12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455@Data@Entityclass LMember { @Id @Column(name = "MEMBER_ID") private int id; private String name; @OneToMany(fetch = FetchType.LAZY, mappedBy = "lMember", cascade = CascadeType.ALL) private List phoneList = new ArrayLi.. 2017. 11. 28. 19. [JPA] 트랜잭션 테스트 JPA를 적용하고 나면 애플리케이션의 트랜잭션 처리가 정상 동작되는지 확인해 볼 필요가 있다.예외가 발생했을 때 rollback 이 되는지를 확인하는 절차가 될 것이다. 스프링에서 지원하는 @Transactional을 이용해 보자.@Transactional 은 선언적 트랜잭션이라 부른다.클래스, 메서드위에 @Transactional 이 추가되면 프록시 오브젝트가 생성되어 요청이 들어왔을 때 이를 가로채고 트랜잭션 처리를 해준다. (메서드 동작 전, 후 처리) 예를 들어 사용자가 회원 정보 수정을 했다고 하자. 처리 순서는 다음과 같을 것이다.1. 사용자가 주소 정보 변경 후 "수정" 버튼 클릭2. 스프링의 Controller -> Service 호출 (updateMember 메서드 위에 @Transact.. 2017. 11. 27. 18. [JPA] N+1 문제 (fetch 조인 해결 방안) fetch 조인을 통해 N+1 문제 해결 방안에 대해서 알아보도록 하자.다음과 같은 테이블 관계가 있다.[테이블 구조]12345678910111213141516create table nplus_order ( id integer not null, primary key (id)) create table nplus_shipping ( id integer not null, order_id integer not null, primary key (id)) create table nplus_order_product ( id integer not null, order_id integer, primary key (id))Colored by Color Scriptercs [엔티티 연관 관계]12345678910111213.. 2017. 11. 24. 17. [JPA] N+1 문제 (@BatchSize 해결 방안) 1번의 쿼리로 A라는 테이블의 데이터 100개를 가져왔다고 하자.헌데 N번의 쿼리가 더 날아가는 상황이 발생했다.내 의도는 한 번의 쿼리로 100개의 데이터를 가져오는게 전부인데 추가적으로 N번의 쿼리가 더 전송되는 문제이다. 이것을 JPA에서 N+1 문제라고 한다. 발생 케이스에 대해서 상세하게 알아보도록 하자.다음과 같이 owner, cat 테이블이 존재한다고 하자.두 테이블의 관계는 owner(1) --> cat(N) 관계이다. [테이블 구조]1234567891011121314151617create table owner ( id integer not null, name varchar(255), primary key (id)) create table cat ( id integer not null, n.. 2017. 11. 23. 14. [JPA] Lock - 잠금 JPA에는 두 가지의 Lock을 제공한다. [낙관적락]트랜잭션 대부분은 충돌이 발생하지 않는다고 낙관적으로 가정하는 방법이다.이것은 데이터베이스가 제공하는 락 기능을 사용하는것이 아니라 JPA가 제공하는 버전 관리 기능을 사용한다.애플리케이션이 제공하는 락이다. 트랜잭션을 커밋하기 전까지는 트랜잭션의 충돌을 알 수 없다. [비관적락]트랜잭션의 충돌이 발생한다고 가정하고 우선적으로 락을 걸고 보는 방법이다.이것은 데이터베이스가 제공하는 락기능을 사용한다.대표적으로 select for update 구문이 있다. JPA에서는 @Version 애노테이션을 통해 낙곽적락을 제공한다.12@Versionprivate int version;cs테이블에 VERSION이라는 컬럼을 생성하고 엔티티 매핑 시 @Version.. 2017. 9. 20. 13. [JPA] 트랜잭션 격리 수준 (Transaction Isolation Level) 격리성은 동시에 실행되는 트랜잭션이 서로에게 영향을 미치지 않도록 격리한다.예를 들어 동시에 같은 데이터를 수정하지 못하도록 해야 한다는 것이다. 격리 수준에는 다음과 같이 4가지가 있다.아래로 갈수록 격리 수준이 높아짐1234READ UNCOMMITTED (커밋되지 않는 읽기)READ COMMITTED (커밋된 읽기)REPEATABLE READ (반복 가능한 읽기)SERIALIZABLE (직렬화 기능)cs [READ UNCOMMITTED - 커밋되지 않는 읽기]트랜잭션 A가 특정 컬럼 데이터를 변경하고 있는 중에(커밋하지 않은 상태) 트랜잭션 B가 read하면 트랜잭션 A가 변경한 데이터를 읽어온다. 이것이 커밋되지 않는 읽기이다.커밋되지 않는 읽기는 dirty read라는 문제가 있다. 이는 트랜잭션.. 2017. 9. 12. 12. [JPA] 복합키 대부분의 엔티티에는 @Id 애노테이션을 한 개 사용한다.하지만 테이블의 키가 복합키로 이뤄져 있다면 엔티티를 설계할 때에 이를 고려해야 한다.복합키 설정 방법은 두 가지가 있다. 12@Embeddable 이용하는 방법@IdClass 이용하는 방법cs 첫 번째 방법이 객체지향 방식에 가깝다고 한다.두 번째 방법은 DB 방식에 가깝다고 하는데 잘 와닿지는 않는다. @Embeddable 이용 방법다음과 같이 emp 테이블이 존재한다.emp 테이블의 키는 emp_name, emp_no 두 개의 복합키로 이뤄져 있다.123456create table emp ( emp_name varchar(255) not null, emp_no integer not null, name varchar(255), primary ke.. 2017. 9. 8. 11. [JPA] Querydsl Querydsl은 오픈 소스 프로젝트이고 type-safe한 쿼리를 위한 Domain Specific Language이다. 왜 필요한가?SQL query는 문자이다.이는 type-check가 불가능하고 실행해 보기 전까지 작동여부 확인이 어렵다.만약 SQL이 class처럼 Type이 있고, Java코드로 작성할 수 있다면 좋지 않을까?SQL을 java로 type-safe하게 개발 할 수 있게 해주는 프레임워크가 Querydsl이다.QueryDSL은 JPQL(HQL)을 type-safe하게 작성하기 위해서 만들어졌고 다음처럼 동작한다.1Querydsl -> JPQL -> SQLcs [Querydsl 테스트 버전]JPA : 2.1hibernate : 5.0.12Querydsl : 4.1.4cs Queryds.. 2017. 9. 1. 10. [JPA] JPQL 테이블이 아닌 객체를 대상으로 검색하는 객체지향 쿼리이다.이게 뭔 말이냐 하면다음과 같이 테이블 명이 JPQL_PERSON 인 Person 엔티티 클래스가 있다.123456@Data@Table(name = "JPQL_PERSON")@Entityclass Person { ... }cs JPQL_PERSON 테이블의 데이터를 모두 추출하고자 할 때 SQL로 작성하게 되면 "select * from JPQL_PERSON" 처럼 될 것이다.그럼 JPQL을 이용하면 어떻게 작성되어야 할까?"select p from Person p" 처럼 하면 된다.이처럼 JPQL은 객체지향쿼리이기 때문에 엔티티 클래스를 기반으로 쿼리를 작성해야 한다. 한번쯤은 궁금해 할지도 모르겠다.왜? "select p from JPQL_PE.. 2017. 8. 28. 9. [JPA] @Enumerated 자바 enum 타입을 엔티티 클래스의 속성으로 사용할 수 있다.@Enumerated 애노테이션에는 두 가지 EnumType이 존재한다.EnumType.ORDINAL : enum 순서 값을 DB에 저장EnumType.STRING : enum 이름을 DB에 저장cs 예를 들어 enum이 다음과 같이 생겼다고 하자.enum Gender { MALE, FEMALE;}cs ORDINAL로 지정하고 gender 속성에 Gender.MALE 값을 셋팅하면 DB에 저장되는 값은 1이다.그럼 Gender.FEMALE 값으로 셋팅하면 어떻게 될까?Gender에 선언되어 있는 순서가 값이 되기 때문에 2가 DB에 저장된다.@Enumerated(EnumType.ORDINAL)private Gender gender;cs STR.. 2017. 8. 23. 8. [JPA] Attribute Converter Attribute Converter에 대해서 알아보자.말 그대로 속성 변환기이다.다음 그림과 같이 엔티티와 DB 사이에서 동작한다.흔히 개발을 진행하다 보면 DB에는 코드성의 데이터가 쌓이게 된다. 가령 gender 컬럼에 존재하는 데이터가 (1 이면 남자) (2 이면 여자)와 같은 식이거나 은행 컬럼에 존재하는 데이터가 (1 이면 신한은행) (2 이면 국민은행)과 같은 경우이다.허나 웹 애플리케이션에서는 DB에 존재하는 1이나 2와 같은 코드성의 데이터를 화면에 출력하는 일은 거의 없을 것이다.화면상에서는 코드에 부여한 의미 있는 문자열을 보여줘야 한다.이런 경우 처리할 수 있는 방법은 entity의 속성에 저장되어 있는 integer 값을 if 조건으로 분기처리하는 방법이 있다.그렇지만 이와 같은 방.. 2017. 8. 23. 7. [JPA] fetch type - 로딩 기법 JPA에는 두 가지 로딩 기법이 존재한다.즉시로딩과 지연로딩이라고 한다.이 두 개의 로딩 전략은 엔티티를 조회할 때 적용된다. update, delete, insert에는 로딩 전략 대상이 아니다. 즉시로딩은 뭔가?엔티티 매니저를 통해 엔티티를 조회하면 연관관계에 매핑되어 있는 엔티티도 함께 조회 지연로딩은 뭔가?엔티티 매니저를 통해 엔티티를 조회하면 연관관계에 매핑되어 있는 엔티티를 실제 사용할 때 조회 즉시로딩, 지연로딩에 대한 설명을 글로만 보면 이해하기 쉽지 않다.예를 들어 설명해보자. Member 엔티티 클래스, Phone 엔티티 클래스가 있다고 하자.이 둘은 서로 객체 연관관계 설정이 되어 있다. 아래와 같이 Member 테이블에 Phone 엔티티가 즉시로딩 전략으로 설정되어 있다고 하자.이와.. 2017. 8. 21. 6. [JPA] 영속성 전이 - Cascade 영속성 전이에 대해 이해하기 위해서는 영속성 컨텍스트의 선행 학습이 필요하다.영속성 컨텍스트가 뭔지 잘 모르겠다면 http://lng1982.tistory.com/273 페이지 읽기를 추천한다. (내가 쓴 글을 내가 추천하니 뭔가 이상하다.) 영속성 전이라는 용어가 다소 생소할 것이다.예를 들어 Member, MemberPhone 엔티티 객체가 존재한다고 하자.Member엔티티를 엔티티매니저를 통해 영속화하면 MemberPhone엔티티도 함께 영속 상태가 되는데 이를 두고 영속성 전이라고 한다. 이처럼 둘의 엔티티가 영속 상태가 되었다면 영속성 컨텍스트가 flush될 때 DB에 insert문이 전송된다. JDBC로 개발 했을 때에는 부모가 되는 Member 테이블에 insert를 먼저 하고 그 다음에 M.. 2017. 8. 17.