코드스테이츠 Day49
- 오전 데일리 코딩
- 31번 문제의 레퍼런스를 이해 못하고, 결국 32번으로 넘어왔다.
하지만 32번도 어려워서 약간 이제부터의 난이도는 내가 풀 난이도가 아닌가 싶다.
데일리 코딩은 포기하고 백준이나 프로그래머스 쉬운 문제푸터 혼자서 풀어볼까 싶다.
- JPA(Java Persistence API)
- ORM(Object-Relational Mapping) : 객체와 DB 테이블의 매핑을 통해, 엔티티 클래스 객체 안에 포함된 정보를 테이블에 저장하는 기술
- JPA의 구현체 : Hibernate ORM, EclipseLink, DataNucleus 등
- 데이터 액세스 계층 = JPA + Hibernate ORM + JDBC API
- 데이터 액세스 계층 상단에 위치한 JPA를 통해서 DB 접근
- JPA : Persistence Context에 엔티티 객체 정보를 보관
- Persistence Context(영속성 컨텍스트) = 1차 캐시 + 쓰기 지연 SQL 저장소
- build.gradle에 추가
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
- yml 파일에 추가
jpa:
hibernate:
ddl-auto: create // 스키마 자동 생성
show-sql: true // SQL 쿼리 출력
- config class에서 샘플 코드 실행
- @Configuration, EntityManager, EntityTransaction, @Bean, CommandLineRunner, EntityManagerFactory, emFactory.createEntityManager();, em.getTransaction();,
return args -> {tx.begin();, em.persist();, em.find();, tx.commit();, em.remove() ...};
- tx.begin() : 트랜잭션 시작
- em.persist() : 1차 캐시에 객체 저장 및 쓰기 지연 저장소에 쿼리 등록
- tx.commit() : 쓰기 지연 저장소의 쿼리를 실행 및 삭제
- em.find(조회할 엔티티 클래스 타입, 식별자 값) : 1차 캐시에서 조회 후, 없으면 테이블에 SELECT 쿼리 전송
- em.remove() : 1차 캐시의 엔티티 객체 제거. 커밋하면 쓰기 지연 장소의 DELETE 쿼리 실행
- setter로 데이터 수정 후 커밋하여 데이터 업데이트 (영속성 컨텍스트에 엔티티 객체 저장 시 스냅샷이 생성되고, 이것을 비교하여 업데이트 여부 확인하는 원리)
- tx.commit() 호출 시, JPA 내부에서 em.flush() 메서드가 호출되어 영속성 컨텍스트의 변경 내용을 데이터베이스에 반영
- entity class
@Getter, @Setter, @NoArgsConstructor, @Entity, @Id, @GeneratedValue
- entity mapping
- 객체-테이블 매핑, 기본키 매핑, 필드(멤버 변수)-컬럼 매핑, 엔티티 간의 연관 관계 매핑 등
1) entity - table mapping
- entity class 필수 : @Entity, @Id, @NoArgsConstructor, @Getter, 기본키 멤버 변수가 파라미터로 들어간 생성자
- 선택 : @Table(name = "") 테이블 이름 설정 가능
- 처음에 오류나서 보니까 Id import 경로 잘못되어서 그런 거였다. 아래 링크 참조.
https://snowdeer.github.io/spring-boot/2019/11/28/spring-boot-no-identifier-specified-for-entity/
2) 기본키 mapping
- 기본키 직접 할당 : @Id
- IDENTITY 전략 : @Id, @GeneratedValue(strategy = GenerationType.IDENTITY), DB에서 기본키를 대신 생성, 객체 생성시 Id 파라미터 안 넣어줘도 됨. AUTO_INCREMENT
- SEQUENCE 전략 : @Id, @GeneratedValue(strategy = GenerationType.SEQUENCE), DB sequence에서 기본키 값 제공, 객체 생성시 Id 파라미터 안 넣어줘도 됨.
- AUTO 전략 : @Id, @GeneratedValue(strategy = GenerationType.AUTO), JPA가 데이터베이스의 Dialect에 따라서 전략 자동 선택. 특정 데이터베이스에 특화된 기능을 사용할 경우
3) 필드(멤버 변수)-컬럼 mapping
- @Column의 디폴트 : @Column(nullable = true, updatable = true, unique = false)
- @Column의 nullable의 기본값이 true이므로, 데이터가 원시 타입인지 확인하고, 래퍼 클래스로 바꾸거나, nullable = false로 바꾸기
- @Column의 다른 애트리뷰트 : length(문자 길이), name(컬럼명) 등
- @Transient: 매핑에서 제외(임시 데이터를 메모리에서 사용하는 용도)
- @Enumerated(EnumType.STRING) : Enum 타입 매핑.
새로운 enum 추가로 순서가 일치하지 않을 경우를 대비해 EnumType.STRING 권장
- LocalDate, LocalDateTime 타입 : @Temporal 생략 가능.
(java.util.Date, java.util.Calendar 타입으로 매핑할 때는 필요)
- entity 클래스에서 발생한 예외는 API 계층까지 전파되므로, API 계층의 GlobalExceptionAdvice에서 캐치(catch) 및 처리 가능
<느낀 점>
오류가 나왔으면 검색해서 해결할 생각을 하자..
요즘 좀 멘탈 와사삭에 지친 것 같다.