2022.12.30.FRI

ronglong·2022년 12월 30일
0
  1. Spring Data JPA를 통한 데이터 액세스 계층 구현
  • Spring Data 패밀리 그룹 : Spring Data JDBC, Spring Data JPA
    -> 유사한 사용 방식, PSA(일관된 서비스 추상화)
  • JPA : Java 애플리케이션에서 관계형 데이터베이스를 사용하기 위해 정해 놓은 명세
  • Hibernate ORM : JPA라는 표준 스펙의 구현체. 실제 사용하는 API.
  • Spring Data JPA : Hibernate ORM 등의 구현체를 쉽게 사용하게 해주는 모듈
    -> 데이터 액세스 계층 구현 (JDBC와 유사)
    1) Repository interface
    - CrudRepository를 대신 JpaRepository 를 상속
    - JPQL을 통한 객체 지향 쿼리 사용
    https://en.wikibooks.org/wiki/Java_Persistence/JPQL
    2) 기타 수정 코드
    - 데이터 타입을 맞추기위해 직접 수동 매핑 코드 구현 필요
  • 과제에서 만든 수동 매핑 코드
@Mapper(componentModel = "spring")
public interface OrderMapper {
    Order orderPostDtoToOrder(OrderPostDto orderPostDto);
    Order orderPatchDtoToOrder(OrderPatchDto orderPatchDto);
    List<OrderResponseDto> ordersToOrderResponseDtos(List<Order> orders);

    default OrderResponseDto orderToOrderResponseDto(Order order){
        // 새 OrderResponseDto 객체 만들고
        OrderResponseDto orderResponseDto = new OrderResponseDto();

        // OrderResponseDto 클래스의 각 필드를 할당
        long memberId = order.getMember().getMemberId();
        List<OrderCoffeeResponseDto> orderCoffees = orderToOrderCoffeeResponseDto(order.getOrderCoffees());

        orderResponseDto.setOrderId(order.getOrderId()); //orderId
        orderResponseDto.setMemberId(memberId); //memberId
        orderResponseDto.setOrderStatus(order.getOrderStatus()); //orderStatus
        orderResponseDto.setOrderCoffees(orderCoffees); //orderCoffees
        orderResponseDto.setCreatedAt(order.getCreatedAt()); //createdAt

        return orderResponseDto;
    }

    default List<OrderCoffeeResponseDto> orderToOrderCoffeeResponseDto(List<OrderCoffee> orderCoffees){
        return orderCoffees.stream()
                .map(orderCoffee -> {
                    return new OrderCoffeeResponseDto(
                            orderCoffee.getCoffee().getCoffeeId(),
                            orderCoffee.getCoffee().getKorName(),
                            orderCoffee.getCoffee().getEngName(),
                            orderCoffee.getCoffee().getPrice(),
                            orderCoffee.getQuantity());
                }).collect(Collectors.toList());
    }
}
  1. [Spring MVC] 트랜잭션(Transaction)
  • TransactionACID 개념은 이전에 공부했음.
    https://velog.io/@youngrong/2022.12.01.THU
  • 커밋(commit) : 모든 작업을 최종적으로 데이터베이스에 반영하는 명령어. 하나의 트랜잭션 종료
  • 롤백(rollback) : 작업 중 문제 발생 시, 트랜잭션 시작 이전으로 되돌아감.
  • JPA에서 tx.commit(); 을 통해 커밋이 진행되는 과정은 굉장히 복잡함.
    '대략' 아래의 클래스들을 거친다. (읽다가 질림.. 만든 사람들 광기 미쳤다.)
    - TransactionImpl
    - JdbcResourceLocalTransactionCoordinatorImpl
    - AbstractLogicalConnectionImplementor
    - JdbcConnection
    - Command
    - SessionLocal
  • 트랜잭션은 데이터베이스에만 한정해서 사용하는 의미는 아님.
    -> 전혀 다른 타입의 리소스(데이터베이스, 파일, 메시지 등)를 하나의 작업 단위로 묶어서 처리해야되는 상황 등
  1. Spring Framework에서의 트랜잭션 처리 -AOP 적용 대상 (부가 기능)
  • 로그 레벨 설정 in application.yml
logging:
  level:
    org:
      springframework:
        orm:
          jpa: DEBUG
  • IntelliJ에서 로그 보기 쉽게 만드는 방법(필터링 유용)
    https://hsik0225.github.io/intellij/2021/04/12/IntelliJ-GrepConsle/
  • 로컬 트랜잭션 (단일 DB) / 분산 트랜잭션 (여러 DB를 하나의 트랜잭션으로 묶어서 처리)
  • 선언형 트랜잭션
    • 비즈니스 로직에 애너테이션을 추가하는 방식
      • @Transactional : 클래스 레벨 or 메서드 레벨
      • @Transactional을 클래스 레벨에 추가하면 해당 클래스에서 Repository의 기능을 이용하는 모든 메서드에 트랜잭션이 적용됨.
      • 체크 예외(checked exeption)는 @Transactional만 추가해서는 rollback이 되지 않음. catch로 넘어가서 처리되기 때문.
        -> catch를 할 필요가 없다면, @Transactional(rollbackFor = {SQLException.class, DataFormatException.class})와 같이 체크 예외를 직접 지정하거나 언체크 예외(unchecked exception)로 감싸서 rollback 가능
      • 메서드 레벨에서 @Transactional(readOnly = true)
        -> 읽기 전용으로, JPA 내부에서 영속성 컨텍스트를 flush 처리하지 않고, 스냅샷도 생성하지 않음
        -> 불필요한 추가 동작 감소. JPA 성능 최적화.
      • @Transactional이 클래스 레벨과 메서드 레벨에 함께 적용된 경우
        -> 메서드 레벨 적용.
      • @Transactional(propagation = Propagation.REQUIRED)
        -> 현재 진행 중인 트랜잭션이 존재하면 해당 트랜잭션을 사용하고, 존재하지 않으면 새 트랜잭션을 생성 (디폴트)
        -> 여러 클래스의 작업을 하나의 트랜잭션으로 묶음.
        https://devlog-wjdrbs96.tistory.com/424
    • AOP로 비즈니스 로직에서 트랜잭션 적용 코드 자체를 감추는 방식
      • AOP 방식으로 트랜잭션을 적용하기 위한 @Configuration 클래스 정의
      • TransactionManager DI
      • 트랜잭션 어드바이스용 TransactionInterceptor @Bean 등록
        1) new NameMatchTransactionAttributeSource();로 애트리뷰트 소스 생성
        2) new RuleBasedTransactionAttribute(); 로 트랜잭션 애트리뷰트 생성
        -> .setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED); 로 propagation 지정
        -> .setReadOnly(true); 추가 설정 가능
        3) 트랜잭션을 적용할 메서드에 트랜잭션 애트리뷰트 매핑
        -> 트랜잭션 애트리뷰트를 Map에 추가. Map의 key를 메서드 이름 패턴으로 지정
        txMethods.put("find*", txFindAttribute);
        -> 트랜잭션 애트리뷰트를 추가한 Map 객체를 txAttributeSource.setNameMap(txMethods); 으로 애트리뷰트 소스에 넘김.
        4) TransactionInterceptor 객체 생성
        -> return new TransactionInterceptor(transactionManager, txAttributeSource);
        5) Advisor @Bean 등록
        -> pointcut 지정
        -> return new DefaultPointcutAdvisor(pointcut, txAdvice());
  1. 오전 데일리 코딩
  • binarySearch(이진탐색 알고리즘(logN)) 해야하는데, 단순 배열 순회(N) 해버리기.. 알고리즘 공부 시급,,
for(int i=0; i<arr.length; i++){
      if(arr[i]==target) return i;
    }
    return -1;

<느낀 점>
어제 처음으로 블로깅 안 했다.
오후 6시 14분부터 14시간 잤음 ;;

요즘 내용이 너무 어려워서 막막하다.
특히 오늘이 역대급이었는데, AOP로 트랜잭션 적용하는 것과 따로 정리는 안 했지만 뒤에 심화로 나온 JTA를 이용한 분산 트랜잭션 적용이 정말 어려웠다.
분산 트랜잭션은 이해 하나도 못 함.

새해부터는 스터디에 들어갈까 생각중이다.

어제까지 수,목 이틀에 걸친 페어 과제는 현재 1번, 2-1번까지 풀었고, 2-2, 2-3 문제를 못 풀었다. 제출 마감은 1월 12일 자정.
새해부터 열심히 해보자.

0개의 댓글