[그리디] 이채현 JPA 6단계 제출합니다 - #267
Conversation
| (1, '', '2024-03-01', 3, 3); | ||
|
|
||
| INSERT INTO reservation (name, date, time_id, theme_id) | ||
| VALUES ('브라운', '2024-03-01', 1, 2); |
There was a problem hiding this comment.
@joincolumn(nullable=false) 선언이 없어서 JPA DDL은 member_id를 nullable로 만들어져 있죠.
이 데이터가 적재되어 있을 때 findAll()을 조회하면 어떤 에러가 발생할까요?
There was a problem hiding this comment.
findAll() 자체는 정상적으로 조회되지만, member의 정보를 조회할때 NuLLpoionterException을 겪을 수 있습니다
| Member member = memberRepository.findByName(name) | ||
| .orElseThrow(); |
There was a problem hiding this comment.
ReservationDao.findByMemberName()이 WHERE r.name = :name 으로 조회하는데,
name은 유니크한 값이 아니라서, 동명이인이 존재할 경우 두 사람의 예약이 함께 반환됩니다.
예를 들어 "김철수"라는 이름의 계정이 두 개라면,
한 사람이 /reservations-mine을 조회할 때 다른 사람의 예약도 노출됩니다. !!
이를 어떻게 해결하면 좋을까요?
There was a problem hiding this comment.
처음에는 ReservationService를 사용해서,
save 메서드에서 name대신 memberId를 조회하는 방식으로 쓰려고 햇으나 기존 member 저장 방식 때문에 다른 name도 불러오게 되는 오류가 발생했습니다.
그 대신,
reservation-mine을 조회할때 member Id로 예약을 불러오는 방식으로 해결했습니다.
| private final Long id; | ||
| private final Member member; | ||
| private final String theme; | ||
| private final String date; | ||
| private final String time; | ||
| private final String name; | ||
|
|
||
| public ReservationResponse(Member member, String name, Long id, String theme, String date, String time) { | ||
| this.member = member; |
There was a problem hiding this comment.
DTO가 객체를 가지고 있을 때 생길 수 있는 문제점들은 어떤 것들이 있을까요?
| @Id | ||
| @GeneratedValue(strategy = GenerationType.IDENTITY) | ||
| private Long id; | ||
|
|
||
| private String name; | ||
| private String email; | ||
| private String password; | ||
| private String role; |
There was a problem hiding this comment.
DB 안에는 email의 unique 제약이 있는 데 엔티티에는 따로 제약사항이 없네요.
이렇게 DB와 엔티티에 제약사항이 다를 경우 생길 수 있는 문제들은 어떤 것들이 있을까요?
There was a problem hiding this comment.
Member Entity에서는 여러개의 email을 넣었을때는 비즈니스적으로는 문제가 발생하지
않지만,
DB 내에서는 unique 제약이 걸려있어서 그 부분에서 충돌이 일어날 수 있을 것 같습니다.
DB안에 unique 제약이 걸려있다고 하셨는데, 어떤 패키지를 통해 확인할 수 있나요?
| import roomescape.member.MemberRepository; | ||
|
|
||
| @Component | ||
| public class LoginInterceptor implements HandlerInterceptor { | ||
|
|
There was a problem hiding this comment.
- admin을 확인하는 과정에서 Filter를 대신 인터셉터를 사용하신 이유가 있을까요?
- Filter란 무엇일까요?
- Interceptor란 무엇일까요?
- Filter와 Interceptor는 각각 어떤 상황에서 쓰일까요?
There was a problem hiding this comment.
필터(Filter)
스프링 외부에서 관리
웹 애플리케이션 전체 적용
주요 용도. 인코딩 변환, xss 방어, cors 설정 등
인터셉터
스프링 컨테이너 내부
특정 url 및 컨트롤러 기준
주요 용도. 로그인 체크, 권한 부여,api 호출 로깅, 실행시간 계산 등..
admin 관리자임을 확인하고 권한 부여한다고 생각해서
인터셉터가 더 적합하다고 생각되었습니다.
There was a problem hiding this comment.
이 get 메서드를 대신할 수 있는 어노테이션을 사용해볼까요?
| protected Member(){ | ||
| } |
There was a problem hiding this comment.
이 생성자 메서드를 대신할 수 있는 어노테이션을 사용해볼까요?
| public class LoginMember { | ||
| @Id | ||
| @GeneratedValue(strategy = GenerationType.IDENTITY) | ||
| private Long id; | ||
| private String name; | ||
| private String email; | ||
| private String password; | ||
| private String role; | ||
|
|
||
| protected LoginMember() { | ||
|
|
||
| } |
There was a problem hiding this comment.
DTO의 역할을 하는 객체인 거 같은 데 ID를 붙여준 이유가 있나요?
이 객체는 DB에 저장되나요?
There was a problem hiding this comment.
entity라고 착각해서,id를 붙여준 것 같습니다.
이 객체는 db에 저장되지 않으므로, @id를 빼는게 나을 것 가타요
| public class LoginMemberArgumentResolver implements HandlerMethodArgumentResolver { | ||
| private final MemberDao memberDao; |
There was a problem hiding this comment.
ArgumentResolver를 만드신 이유가 무엇인가요?
어떤 걸 편리하게 하기 위함이죠??
There was a problem hiding this comment.
로그인하는 멤버를 잡아서, 로그인을 확인하고 admin 권한을 가지고 있는 사람에게 권한을 부여해줍니다
|
|
||
| import roomescape.member.Member; | ||
|
|
||
| public class ReservationResponse { |
There was a problem hiding this comment.
채현님께서 어떤 DTO는 class 자료형을 사용하고 어떤 DTO는 record자료형을 사용하고 계신 거 같아요.
class DTO와 record DTO를 정하신 채현님만의 기준이 있으신가요?
There was a problem hiding this comment.
아직 무엇이 더 좋을지 몰라서, 둘다 써보고 있습니다.
혜빈 리뷰어님은 어떤게 더 좋은 것 같나요?
제가 느끼기에는 entity에는 class를 쓰는게 맞는 것 같은데 response와 같이 단순 dto면 다 record로 바꿔도 상관 없는 것 같다고 느껴져요
| private final ThemeRepository themeRepository; | ||
| private final TimeRepository timeRepository; | ||
| private final MemberRepository memberRepository; | ||
| private final WaitingRepository waitingRepository; |
There was a problem hiding this comment.
WaitingRepository가 없어서 컴파일이 안 되는 데 혹시 서비스 테스트를 어떻게 하셨나용...?
파일 넣어주셔야 할 거 같아요!
| public Theme create(Theme theme){ | ||
| return themeRepository.save(theme); | ||
| } | ||
|
|
||
| public void delete(Long id){ | ||
| themeRepository.deleteById(id); | ||
| } | ||
|
|
||
| public List<Theme> findAll(){ | ||
| return themeRepository.findAll(); | ||
| } |
There was a problem hiding this comment.
JPA(지난 번 미션)와 비교해서 Spring Data JPA는 어떤 점들이 편리했나요?
코드를 구현하시면서 어떤 점들이 보다 더 편리하다고 느꼈는 지 채현님의 의견이 궁금해욥!
There was a problem hiding this comment.
Entity Manager의 경우에는 일일히 모든 것들을 입력해줘야해서 조금 더 손이 가는 느낌이였더라면, JPA는 일정한 것들을 대신해주니까 매우 편리하다는 느낌이 들었어요!
| private String value; | ||
| private String timeValue; |
There was a problem hiding this comment.
value라고 했을때, 어떠한 value인지 불명확하다고 생각되어서, 직관성이 부족하다는 느낌이 들었습니다.
timeValue이면 시간에 관한 value임을 알 수 있을 것 같아 이렇게 변경하게 되었습니다.
| public Waiting(Member member, String date, Theme theme, Time time) { | ||
| this.member = member; | ||
| this.date = date; | ||
| this.theme = theme; | ||
| this.time = time; | ||
| } |
There was a problem hiding this comment.
Lombok의 @builder 키워드에 대해 알아보시는 것도 좋을 것 같아요!
가독성 향상이나 생성자 파라미터 순서 실수를 줄이는 데 큰 도움이 되니 프로젝트 들어가기 전에 한 번 알아보깅~~
| @ManyToOne | ||
| @JoinColumn(name = "member_id") | ||
| private Member member; | ||
|
|
||
| @ManyToOne | ||
| @JoinColumn(name = "theme_id") | ||
| private Theme theme; | ||
|
|
||
| @ManyToOne | ||
| @JoinColumn(name = "time_id") | ||
| private Time time; |
There was a problem hiding this comment.
- FK값을 Waiting에 두신 이유가 있나요?
- @manytoone 어노테이션의 역할은 무엇이죠?
- 이 어노테이션이 붙었을 때 데이터베이스 테이블표는 어떻게 구성되나요?
There was a problem hiding this comment.
FK 값을 Waiting에 두신 이유가 있나요?
Fk는 많은 데이터 테이블을 가질때 일반적으로 쓰입니다/
ex. 회원 한명은 여러 개의 대기 신청을 할 수 있음.등..
에서 알 수 있습니다.
@manytoone 어노테이션의 역할은 무엇인가요?
여러 개의 waiting이 하나의 member를 참조
여러개의 waiting이 하나의 theme을 참조
등.. 을 의미합니다
이 어노테이션이 붙었을때 데이터베이스 테이블표는 어떻게 구성되나요?
FK를 포함한 데이터 테이블이 생성될 것 같습니다
|
#266 (comment)
WaitingRepository 추가 하신 뒤에 회원가입이 잘 동작하는 지 확인해주시면, |

🙋♂️인사🙋♂️
안녕하세요. 세종대학교 그리디 백엔드 4기 이채현입니다.
이번주는 꽤나 여유로워서 많은 시간을 투자할 수 있을 것 같아요! 많은 피드백 부탁드립니다.!!!
Spring JPA 4-6단계 Entity Manager-> JPA
entity매니저를 사용해서 repository 수정
jpa 전환 및 내 예약 구성코드를 생성함.
고민한 내용 🤔
EntityManager를 JPA로 바꾸려면 어떠한 형식을 가져야 하는가 고민했습니다.
사용해보니, JPA가 EntityManager보다 더 적은 메서드를 쓰고도 충분히 구현되는 것 같습니다.!
실무에서는 JPA를 더 많이 사용하게 될 것 같은데, EntityManager를 사용하게 되는 경우도 있나요?
그리고 Entity에서 단순히 protected를 추가한 것 만으로, 테스트가 돌아가는 경우가 있는데
이 protected의 의미를 잘 모르겠습니다.