Skip to content

2unmini/plus_week

 
 

Repository files navigation

플러스 주차 개인과제 기반 코드입니다.

필수과제 풀이

Q1.TODO 1.

A.

img.png

@Transaction의 어노테이션을 붙이면 해당 메소드내 데이터베이스 접근이 하나의 작업단위로 묶인다. 하나의 트랜잭션의 작업은 완전히 커밋되거나 완전히 롤백되어야한다. = 원자성

Q2. TODO 2.

A.

img_1.png ADMIN 권한이 필요한 API를 만든다.

  • 필터를 사용할 경우 img_2.png

  • 인터셉터를 사용할 경우 (필터 주석) img_3.png ADMIN 인터셉터를 만든후 img_4.png 사용하고자 하는 인터셉트와 위에서 설정한 API와 순서를 지정한다. img_5.png 이런 결과가 나옴

  • 수정 img_7.png /reservations일때 /* 하위 하나의 경로에 대해서만 적용 /**는 하위 모든 경로에 대해서 적용

Q3. TODO 3.

페치조인을사용

수정 전 쿼리
Hibernate: 
    select
        r1_0.id,
        r1_0.end_at,
        r1_0.item_id,
        r1_0.start_at,
        r1_0.status,
        r1_0.user_id 
    from
        reservation r1_0
Hibernate: 
    select
        i1_0.id,
        i1_0.description,
        m1_0.id,
        m1_0.email,
        m1_0.nickname,
        m1_0.password,
        m1_0.role,
        m1_0.status,
        i1_0.name,
        o1_0.id,
        o1_0.email,
        o1_0.nickname,
        o1_0.password,
        o1_0.role,
        o1_0.status,
        i1_0.status 
    from
        item i1_0 
    left join
        user m1_0 
            on m1_0.id=i1_0.manager_id 
    left join
        user o1_0 
            on o1_0.id=i1_0.owner_id 
    where
        i1_0.id=?

A.

수정 후 쿼리
Hibernate: 
    select
        r1_0.id,
        r1_0.end_at,
        i1_0.id,
        i1_0.description,
        i1_0.manager_id,
        i1_0.name,
        i1_0.owner_id,
        i1_0.status,
        r1_0.start_at,
        r1_0.status,
        u1_0.id,
        u1_0.email,
        u1_0.nickname,
        u1_0.password,
        u1_0.role,
        u1_0.status 
    from
        reservation r1_0 
    join
        item i1_0 
            on i1_0.id=r1_0.item_id 
    join
        user u1_0 
            on u1_0.id=r1_0.user_id

Q4. TODO 4.

A.

@Transactional
    public void reportUsers(List<Long> userIds) {
        List<User> users = userRepository.findAllById(userIds);

       if(userIds.size()!=users.size()) {
           throw new IllegalArgumentException("해당 ID에 맞는 값이 존재하지 않습니다.");
       }
       for(User user:users){
           user.updateStatusToBlocked();
       }
    }

피드백 후

for (User user : users) {
            user.updateStatusToBlocked();
        }

메소드를 디비에서 업데이트 해주는 방법을 추천받았다

img_9.png

Q5. TODO 5.

A.

QueryDSL 관련 셋팅 후 페치조인으로 N+1문제 해결

@Override
    public List<Reservation> getReservationByUserIdOrItemId(Long userId, Long itemId) {
        QReservation reservation = QReservation.reservation;

        return jpaQueryFactory.select(reservation)
                .from(reservation)
                .innerJoin(reservation.user).fetchJoin()
                .innerJoin(reservation.item).fetchJoin()
                .where(reservation.user.id.eq(userId).and(reservation.item.id.eq(itemId)))
                .fetch();
    }

Q6. TODO 6.

A.

img_6.png

Q7. TODO 7.

A.

  • 개선1. 필요하지 않은 else구문을 걷어 냅니다.
 switch (status) {
            case "APPROVED": {
                if (!"PENDING".equals(reservation.getStatus())) {
                    throw new IllegalArgumentException("PENDING 상태만 APPROVED로 변경 가능합니다.");
                }
                break;
            }
            case "CANCELED": {
                if ("EXPIRED".equals(reservation.getStatus())) {
                    throw new IllegalArgumentException("EXPIRED 상태인 예약은 취소할 수 없습니다.");
                }
                break;
            }
            case "EXPIRED": {
                if (!"PENDING".equals(reservation.getStatus())) {
                    throw new IllegalArgumentException("PENDING 상태만 EXPIRED로 변경 가능합니다.");
                }

                break;
            }
            default: {
                throw new IllegalArgumentException("올바르지 않은 상태: " + status);
            }
        }
        reservation.updateStatus(status);

중간 피드백 후 이 코드 역할(status에따라 상태가 바뀌는)을 Status클래스가 해주면 어떨까 라는 피드백을 받고

public enum ReservationStatus {
    PENDING("PENDING") {
        @Override
        public boolean canChangeTo(ReservationStatus status) {
            switch (status) {
                case APPROVED, CANCELED, EXPIRED -> {
                    return true;
                }
            }
            return false;
        }
    }, APPROVED("APPROVED") {
        @Override
        public boolean canChangeTo(ReservationStatus status) {
            return status.equals(APPROVED);
        }
    }, CANCELED("CANCELED") {
        @Override
        public boolean canChangeTo(ReservationStatus status) {
            return status.equals(CANCELED);
        }
    }, EXPIRED("EXPIRED") {
        @Override
        public boolean canChangeTo(ReservationStatus status) {
            return status.equals(EXPIRED);
        }
    };

이렇게 필요한 메서드를 만들어 사용하였다.

  • 개선2.컨트롤러 응답 데이터 타입을 적절하게 변경합니다.
  • 개선3.재사용 비중이 높은 findById 함수들을 default 메소드로 선언합니다.
  • user쪽에서 중복으로 사용되던 findById함수를
default User findByIdOrElseThrow(Long id){
return findById(id).orElseThrow(() -> new IllegalArgumentException("해당 ID에 맞는 값이 존재하지 않습니다."));
}
  • 개선4.상태 값을 명확하게 enum으로 관리 합니다.
  • 개선5.첫번째 Transaction문제를 해결 했다면 RentalLogService save함수 내19~21번째 코드를 삭제하거나 주석처리하여 기능이 동작하도록 수정합니다..

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Java 100.0%