개발자로서 살아남기/JPA 이슈 및 최적화 8

서버개발자로서 살아남기 - JPA 사용시 조회방법에 따른 영속성 여부

개요스터디에서 Spring-JPA 환경에서, 쿼리메소드와 @Query 어노테이션을 이용한 JPQL, 네이티브 쿼리을 활용한 조회에 대해 이야기를 하다가, 3개의 조회방법 중 어떤 방법이 영속될까 라는 궁금증이 생겼다.위에서 언급했던 3가지 조회 방법에 대해 영속성 여부을 알아보기로 한다쿼리메서드Query 어노테이션을 활용한 JPQLQuery 어노테이션을 활용한 네이티브 쿼리 테스트관련 내용을 리서치해보는 것도 좋지만, 일단 아묻따 테스트코드를 작성해서 영속성 여부를 확인하였다.사용할 테이블은 회원 정보가 있는 테이블이고, Pk는 memberId이다. 세팅@Autowired private MemberRepository memberRepository; @Autowired private EntityMan..

Spring boot + JPA 환경에서 Insert 동시 요청 시 처리방법

개요 이전에 회사에서 멀티스레딩 환경에서 동시성 이슈 관련해서 글을 작성한 적이 있다. 그 때는 동시성 이슈 즉 insert 요청이 동시에 온다면 락(LOCK)을 걸어 처리하는 방법을 제시하였다. Spring boot + JPA 환경에서 비관적 vs 낙관적 Lock 선택하기 - https://code-killer.tistory.com/163 사내에서도 해당 방법으로 처리하려던 와중 큰 프로젝트에 참여하게 되었고, 위 이슈는 크리티컬하지 않았기 때문에, 추후 개선 이슈로 놔두었다. 큰 프로젝트가 마무리 되고, 해당 이슈를 다시 살펴보는데, 그땐 생각하지 못했던 의문들이 떠올랐다. "그때 당시에는 동시 요청이 오니까, 일단 락을 걸어 비동기로 처리를 해야겠다." 라고 단순히 생각했었는데 정확히 따지자면, 1..

비관적 락, 낙관적 락 사용시 deadlock 관련 이슈들

개요 스카우터 알람 설정 이후, 간헐적으로 에러가 발생하는 API가 2건 있었다. 급한 이슈는 아니였기에, 우선순위를 뒤로 미뤘었는데, 스카우터 알림방에 빨간색 에러 메시지를 보니까 도저히 그냥 지나칠 수 없었다..(개발자 특) 참고로 아래에 나오는 내용은 낙관적 Lock과 비관적 Lock을 알고 있어야 하는 내용이다. https://code-killer.tistory.com/163 멀티스레딩 환경에서의 동시성 이슈 첫번째 이슈는 select 쿼리 이후, 조건에 따라 insert을 하는 로직이였는데, 동시요청이 들어오면 당연한 결과지만, Duplicate primary Key 에러가 발생했다. Exception - org.springframework.dao.DataIntegrityViolationExce..

Spring boot + JPA 환경에서 비관적 vs 낙관적 Lock 선택하기

개요 회사에서 Spring boot + JPA + mysql 조합을 사용하는 프로젝트가 있는데, PK 중복 문제로 update 시 문제가 발생하였다. 추적 결과 기존 코드는 멀티스레딩 환경에서 조건적으로 동시성 이슈로 생기는 문제였다. 비관적 락, 낙관적 락을 사용하여 해당 이슈를 해결해보기로 한다. 비관적 락 이름 그대로 트랜잭션끼리 충돌을 발생한다고 가정(비관적 락)하여 우선 락을 거는 방법이다. DB의 Lock 기능을 이용한다. (쿼리에 Select for update 구문이 들어감) Lock을 획득할 때까지 트랜잭션은 대기하므로, Timeout 설정 가능 낙관적 락 이름 그대로 트랜잭션 끼리 충돌나지 않는다고 가정하고(낙관적 락)하여 커밋 시 충돌을 알 수 있다. DB Lock 기능을 이용하지 않..

Spring Boot + JPA 환경에서 변경 감지(dirty checking)와 병합(merge)

변경감지와 병합(merge) 병합은 대부분이 알고있는 엔티티 매니저의 merge 메서드이다. 여기서 변경감지(dirty checking)은 JPA의 특징 중 하나이며 entity의 값만 바꿔주면 알아서 변경감지(dirty checking)를 하여 update 쿼리문을 날린다. 준영속 엔티티 영속성 컨텍스트가 더는 관리하지 않는 엔티티 문제는 준영속 엔티티인 경우 JPA가 관리하지 않음으로 어떻게 update을 할 지 애매한 경우이다. 그 때는 2가지 방법을 이용할 수 있다. 변경 감지 기능 사용 병합(merge) 사용 변경 감지 기능 사용 @Transactional public void update(Long id, Entity entity) { // entity를 가져온다. Entity entity = ..

JPA - saveAll vs save (2)

saveAll()과 save()의 내부구현 save() 메서드의 구현 코드이다. @Transactional @Override public S save(S entity) { Assert.notNull(entity, "Entity must not be null."); if (entityInformation.isNew(entity)) { em.persist(entity); return entity; } else { return em.merge(entity); } } saveAll() 메서드의 구현 코드이다. @Transactional @Override public List saveAll(Iterable entities) { Assert.notNull(entities, "Entities must not be n..

JPA - saveAll vs save (1)

JPA에서 여러개의 데이터를 DB에 INSERT 할 때saveALL()을 이용하면 성능 좋게 사용할 수 있다. save() 사용 save() 메서드의 구현 코드이다. @Transactional @Override public S save(S entity) { Assert.notNull(entity, "Entity must not be null."); if (entityInformation.isNew(entity)) { em.persist(entity); return entity; } else { return em.merge(entity); } } entityManager를 통해 새로 들어가면 persist, 기존에 있다면 merge 을실행한다. Mysql 문법으로 보면 아래와 같다. INSERT INTO ..

728x90