spring/JPA(19)
-
트랜잭션과 락(3) - 낙관적 락, 비관적 락
낙관적 락 JPA가 제공하는 낙관적 락은 버전(@Version)을 사용한다. 낙관적 락은 트랜잭션을 커밋하는 시점에 충돌을 알 수 있다는 특징이 있다. 락 옵션 없이 @Version만 있어도 낙관적 락이 적용된다. 락 옵션을 사용하면 더 세밀하게 락을 제어할 수 있다. 옵션 1. NONE 락 옵션을 적용하지 않아도 엔티티에 @Version이 적용된 필드만 있으면 낙관적 락이 적용된다. - 용도 조회한 엔티티를 수정할 때 다른 트랜잭션에 의해 변경되지 않아야 한다. 조회 시점부터 수정 시점까지를 보장한다. - 동작 엔티티를 수정할 때 버전을 체크하면서 버전을 증가한다. 이때 데이터베이스의 버전 값이 현재 버전이 아니면 예외가 발생한다. - 이점 두번의 갱신 분실 문제를 예방한다. 2. OPTIMISTIC ..
2024.02.15 -
트랜잭션과 락(2) - 락 기본
낙관적 락과 비관적 락 들어가기에 앞서... JPA의 영속성 컨텍스트(1차 캐시)를 적절히 활용하면 데이터베이스 트랜잭션이 READ COMMITTED 격리 ㅅ준이어도 애플리케이션 레벨에서 반복 가능한 읽기가 가능하다. => 다시 조회할 때 1차 캐시에 저장된 엔티티를 조회하기 때문 엔티티가 아닌 스칼라 값을 직접 조회하면 영속성 컨텍스트의 관리를 받지 못하므로 반복 가능한 읽기를 할 수 없다. JPA는 데이터베이스 트랜잭션 격리 수준을 READ COMMITTED 정도로 가정한다. 만약 중요한 비즈니스 로직에 더 높은 격리 수준이 필요하다면 낙관적 락과 비간적 락 중 하나를 사용하면 된다. 낙관적 락은 이름 그대로 트랜잭션 충돌이 발생하지 않는다고 낙관적으로 가정하는 방법이다. 이것은 데이터베이스가 제공하..
2024.02.15 -
트랜잭션과 락(1)
트랜잭션과 격리 수준 트랜잭션은 원자성, 일관성, 격리성, 지속성을 보장해야 한다. - 원자성 : 트랜잭션 내에서 실행항 작업들은 하나의 작업처럼 모두 성공하든가 모두 실패해야 한다. - 일관성 : 모든 트랜잭션은 데이터베이스에서 정한 무결성 제약 조건을 항상 만족해야 한다. - 격리성 : 동시에 실행되는 트랜잭션들이 서로에게 영향을 미치지 않도록 격리한다. => 예를 들어 동시에 같은 데이터를 수정하지 못하도록 한다. - 지속성 : 트랜잭션을 성곡적으로 끝내면 그 결과가 기록되어야 한다. 중간에 시스템에 문제가 생겨도 성공한 트랜잭션 내용을 복구해야 한다. 트랜잭션은 원자성, 일관성, 지속성을 보장한다. 하지만 격리성을 완벽하게 보장하려면 트랜잭션을 거의 차례대로 실행해야 한다. 이렇게 하면 동시성 처..
2024.02.15 -
성능 최적화(4) - 트랜잭션을 지원하는 쓰기 지연과 성능 최적화
트랜잭션을 지원하는 쓰기 지연과 JDBC 배치 SQL을 직접 다루는 경우를 생각해보자 insert(member1); insert(member2); insert(member3); insert(member4); insert(member5); commit(); 네트워크 호출 한 번은 단순한 메소드를 수만 번 호출하는 것보다 더 큰 비용이 든다. 위 코드는 5번의 INSERT SQL과 1번의 커밋으로 총 6번 데이터베이스와 통신한다. 이것을 최적화하려면 한 번에 데이터베이스로 보내면 된다. JDBC가 제공하는 SQL 배치 기능을 사용하면 SQL을 모아서 데이터베이스에 한번에 보낼 수 있지만 코드 수정량이 많아진다. 또 비즈니스 로직이 복잡한 곳에서는 사용하기 쉽지 않다. 따라서 SQL 배치는 수천 건 이상의 데..
2024.02.15 -
성능 최적화(3) - 배치 처리
수백만 건의 데이터를 배치 처리해야 하는 상황이라 가정해보자. 일반적인 방식으로 엔티티를 게속 조회하면 영속성 컨텍스트에 아주 많은 엔티티가 쌓이면서 메모리 부족 오류가 발생한다. 따라서 이런 배치 처리는 적절한 단위로 영속성 콘텍스트를 초기화해야 한다. 또한 2차 캐시를 사용하고 있다면 2차 캐시에 엔티티를 보관하지 않도록 주의해야 한다. JPA 등록 배치 수만 건 이상의 엔티티를 한 번에 등록할 때 주의할 점은 영속성 컨텍스트에 엔티티가 계속 쌓이지 않도록 일정 단위마다 영속성 컨텍스트의 엔티티를 데이터베이스에 플러시하고 영속성 컨텍스트를 초기화해야 한다. public static void main(String[] args) { EntityManagerFactory emf = Persistence.c..
2024.02.13 -
성능 최적화(2) - 읽기 전용
엔티티가 영속성 컨텍스트에 관리되면 1차 캐시부터 변경 감지까지 얻을 수 있는 혜택이 많다. 하지만 영속성 컨텍스트는 변감 감지를 위해 스냅샷 인스턴스를 보관하므로 더 많은 메모리를 사용하는 단점이 있다.만약 조회한 데이터를 수정할 일이 없고 같은 트랜잭션 안에서 다시 읽어들일 일도 없다면 읽기 전용으로 엔티티를 조회해서 메모리 사용량을 최적화 할 수 있다. select o from Order o 1. 스칼라 타입으로 조회 가장 황실한 방법은 다음처럼 엔티티가 아닌 스칼라 타입으로 모든 필드를 조회하는 것이다. 엔티티가 아니므로 영속성 컨텍스트가 결과를 관리하지 않는다. select o.id, o.name, o.price from Order o 2. 읽기 전용 쿼리 힌트 사용 하이버네이트 전용 힌트인 o..
2024.02.13 -
성능 최적화(1) - N+1
N+1 지연로딩과 N+1 JPA로 애플리케이션을 개발할 때 성능상 가장 주의해야 한다. =============================회원 1================================= @Entity @Getter @Setter public class Member { @Id @GeneratedValue @Column(name = "member_id") private Long id; private String username; @Embedded private Address address; @JsonIgnore @OneToMany(mappedBy = "member") private List orders = new ArrayList(); } ==========================..
2024.02.07 -
JPQL(3) - 페이징, 조인
페이징 JPA는 페이징을 처리하는 API를 제공한다. - setFirstResult(int startPosition) : 조회 시작 위치 - setMaxResults(int maxResult) : 조회할 데이터 수 List resultList = em.createQuery("select m from Member m order by m.age desc", Member.class) .setFirstResult(10) .setMaxResults(20) .getResultList(); 위 예제는 11번째부터 시작해서 20건의 데이터를 조회한다.(11~30) 조인 JPQL도 조인을 지원한다. SQL과 거의 동일하고 문법만 약간 다르다. -내부조인 List resultList = em.createQuery("sel..
2024.01.25 -
JPQL(2) - 프로젝션
SELECT 절에 조회할 대상을 지정하는 것을 프로젝션이라 한다. 프로젝션 대상은 다음과 같다. 1. 엔티티 2. 엠비디드 타입 3. 스칼라 타입이(숫자, 문자 등 기본 데이터) 엔티티 프로젝션 SELECT m FROM Member m //회원 SELECT m.team FROM Member m // 팀 위 두 쿼리는 모두 엔티티를 프로젝션 대상으로 사용했다. 객체를 바로 조회한 것인데 컬럼을 하나하나 나열해서 조회해야 하는 SQL과 차이가 있다. 이렇게 조회된 엔티티는 영속성 컨텍스트에서 관리된다. 임베디드 타입 프로젝션 JPQL에서 임베디드 타입은 엔티티와 거의 비슷하게 사용된다. (임베디드 타입은 조회의 시작점이 될 수 없다.) => 테이블이 아니기 때문 아래 코드는 잘못된 예이다. SELECT a ..
2024.01.24