* 요즘 헬스장을 오가며 제일 많이 듣는 앨범입니다. 오고 가는 거리는 걸어서 편도 10분이 걸립니다. 처음엔 유툽 알고리즘이 추천을 해줬는데, 들을수록 정말 제 스타일인 부분이 많더라고요! 나중에 시간이 되면 이런 음악도 만들어보고 싶습니다:)
Member 엔티티 클래스 필드와 열 간의 매핑
🚨 기본키 생성 전략은 데이터베이스에서 지원해주는 AUTO_INCREMENT 또는 SEQUENCE를 이용할 수 있도록 IDENTITY 또는 SEQUENCE 전략을 사용하는 것이 좋습니다.
◾ IDENTITY 전략 : 기본키 생성을 위해 데이터베이스에 위임하는 전략입니다.
◾ SEQUENCE 전략 : 데이터베이스에서 제공하는 시퀀스를 사용해서 기본키를 생성하는 전략입니다.
✔ 테스트_01 : PersistenceException
IDENTITY 전략으로 기본키를 생성해 주고, 매핑을 해보는 연습을 하며 exception을 터뜨리는 것을 연습하고 있습니다.
Member 클래스 중
private String email;
JpaColumnMappingConfig 클래스 중
tx.begin();
em.persist(new Member());
tx.commit();
}
Member 클래스에서 email 필드의 설정은 nullable = false로 되어 있습니다. 하지만 JpaColumnMappingConfig 테스트에서는 email 필드에 아무 값도 입력하지 않고 데이터를 저장하였습니다. 때문에 에러가 발생해야 합니다.
학습내용대로 했는데도 불구하고 exception이 터지지 않아 난항을 겪고 있던 와중에 설마...? 하고 패키지 밖에 있는 class 하나를 삭제했습니다. 그랬더니 exception이 아래와 같이 잘 터지는 것을 확인할 수 있었습니다.
java.lang.IllegalStateException: Failed to execute CommandLineRunner
.
.
.
Caused by: javax.persistence.PersistenceException
org.hibernate.PropertyValueException: not-null property references a null or transient value
아무래도 패키지 밖에 있는 것이 우선순위로 실행되었나봅니다. 😥
자. exception이 잘 터졌습니다.
null이 아닌 입력 값이 있어야 하는데 test 코드에서는 입력값이 없었습니다. 입력값이 없으니 PropertyValueException을 래핑한 PersistenceException이 발생했습니다. 따라서, nullable = false는 정상적으로 동작했음을 확인할 수 있습니다.
* 참고로 엔티티 클래스에서 발생한 예외는 API 계층까지 전파되며, 따라서 API 계층의 GlobalExceptionAdvice에서 캐치(catch) 한 후 처리할 수 있습니다.
Member 클래스 엔티티 매핑과 @Column 애너테이션
private String name;
◾ 문자 길이의 디폴트 값은 255이나 이름은 그리 길지 않아도 되어서 100으로 지정
private LocalDateTime createdAt = LocalDateTime.now();
◾ Member가 등록될 때 시간 및 날짜를 매핑하기 위한 필드
◾ java.util.Date, java.util.Calender 타입으로 매핑하려면 @Temporal 애너테이션 추가해야함
◾ 하지만 LocalDateTime의 경우 @Temporal 생략 가능
◾ LocalDateTime 열은 TIMESTAMP 타입과 매핑됨
◾ createdAt 필드에 LocalDateTime.now() 메서드로 현재 시간 정보를 필드에 전달함
private LocalDateTime modifiedAt = LocalDateTime.now();
◾ name 애트리뷰트에 별도의 이름을 지정하여 엔티티 클래스 필드명과 다른 이름으로 열 생성
private String age;
◾ @Transient 애너테이션을 필드에 추가하면 테이블 열과 매핑하지 않겠다는 의미로 JPA가 인식함
◾ 따라서 데이터베이스 저장 x, 조회시 매핑 x
◾ @Transient는 주로 임시 데이터를 메모리에서 사용하기 위한 용도로 쓰임
Order 클래스 엔티티 매핑, @Enumerated 애너테이션
private OrderStatus orderStatus = OrderStatus.ORDER_REQUEST;
◾ @Enumerated 애너테이션은 enum 타입과 매핑할 때 사용하는 애너테이션으로 두 가지 타입을 가질 수 있다.
◾ EnumType.ORDINAL : enum의 순서를 나타내는 숫자를 테이블에 저장
🚨 주의사항 : ORDINAL로 지정할 경우 기존에 정의되어 있는 enum 사이에 새로운 enum 하나가 추가된다면
그때부터 테이블에 저장되어 있는 enum 순서 번호와 enum에 정의되어 있는 순서가 일치하지 않게됨
🚨 따라서 이런 문제가 발생하는 것을 예방하기 위해 처음부터 EnumType.STRING 사용을 권장합니다.
◾ EnumType.STRING : enum의 이름을 테이블에 저장
마무리
🚨 클래스 이름 중복 등 특별한 이유가 없다면 @Entity와 @Id 만 추가합니다. 단, 엔티티 클래스가 테이블 스키마 명세의 역할을 하길 원하면 @Table 애너테이션에 테이블명을 지정할 수 있습니다.
JPA를 처음 접하는 저는 너무나도 어려워서 또다시 벽 앞에 서있는 기분이 듭니다.
그러나 어쩌겠습니까! 물 한 잔 마시고 열심히 해야지요!
요즘 주 5일이상 운동을 해서 힘이 더 넘치게 되었습니다.
그럼 이 포스팅을 보신 모든 분들, 화이팅하는 하루 되시길 바랍니다 😊
🚨 이 글은 개인 학습을 위한 기록입니다. 잘못된 정보가 상당수 있을 수 있습니다.
'코딩하는 코커두드 > 자바, 스프링 백엔드 과정' 카테고리의 다른 글
Day 53 _ 장마의 시작, 휴가, 트랜잭션 (20230627) (0) | 2023.06.29 |
---|---|
Day 52 _ 트랜젝션 들어가기 전, 연관관계 매핑 등 (20230626) (0) | 2023.06.28 |
Day 50 _ 모든 것은 작은 실수에서 비롯된다 (20230622) (0) | 2023.06.23 |
Day 49 _ service 계층 재학습, 매퍼(mapper) (20230621) (0) | 2023.06.22 |
스프링 부트 Custom Annotation (0) | 2023.06.21 |