JDBC 로 직접 SQL을 작성했을때의 문제
이 문제 해결을 위해 처음으로 Persistence Framework 등장!
SQL Mapper (QueryMapper)
해결법 : 매핑정보에 상속정보를 넣어준다(@OneToMany, @ManyToOne)
해결방법 : 매핑정보에 방향정보를 넣어준다. (
@JoinColumn
,@MappedBy
)
해결방법 : 매핑/조회 정보로 참조탐색 시점을 관리한다.(
@FetchType
,fetchJoin()
)
해결방법 : 크기가 큰 멤버 객체는 테이블을 분리하여 상속으로 처리한다. (
@embedded
)
♂️ 해결방법 : PK 를 객체 Id로 설정하고 EntityManager는 해당 값으로 객체를 식별하여 관리 한다.(
@Id
,@GeneratedValue
)
캐싱 기능은 객체 지향 프로그래밍이 가진 가장 큰 장점이다.
1차 캐시
2차 캐시
@Cacheable
적용 후 설정 추가 @Entity
@Cacheable
public class Team {
# application.yml
spring.jpa.properties.hibernate.cache.use_second_level_cache: true
# 2차 캐시 활성화합니다.
spring.jpa.properties.hibernate.cache.region.factory_class: XXX
# 2차 캐시를 처리할 클래스를 지정합니다.
spring.jpa.properties.hibernate.generate_statistics: true
# 하이버네이트가 여러 통계정보를 출력하게 해주는데 캐시 적용 여부를 확인할 수 있습니다.
# appplication.yml
spring.jpa.properties.javax.persistence.sharedCache.mode: ENABLE_SELECTIVE
cache mode 종류 | 내용 |
---|---|
ALL | 모든 엔티티를 캐시합니다. |
NONE | 캐시를 사용하지 않습니다. |
ENABLE_SELECTIVE | Cacheable(true)로 설정된 엔티티만 캐시를 적용합니다. |
DISABLE_SELECTIVE | 모든 엔티티를 캐시하는데 Cacheable(false)만 캐시하지 습니다. |
UNSPECIFIED | JPA 구현체가 정의한 설정을 따릅니다 |
영속성 4가지 상태 ( 비영속 > 영속 > 준영속 | 삭제)
키 생성전략이
generationType.IDENTITY
로 설정 되어있는 경우 생성쿼리는 쓰기지연이 발생하지 못한다.
- why? 단일 쿼리로 수행함으로써 외부 트랜잭션에 의한 중복키 생성을 방지하여 단일키를 보장한다.
flush는 DB에 쿼리가 전송되었으나 반영이 안된상태로
git으로 이야기 할것같으면 commit을 하고 push를 하지 않은 반영 대기 상태이다
트랜잭션1 에서 업데이트하거나 추가한 내용을 트랜잭션2 에서는 알수없다.
아니면 pull request를 하고 다른 사람들이 모여서 회의 하면서 이것을 반영할지 안할지 토론하는 준비단계이기도 하다.
현실로는 판매자가 택배를 출발 시켰을때의 상태이다 아직 도착하여 고객이 받지 못했다. 취소가 가능하다
commit은 flush가 된것을 DB에 적용시키는것으로
commit이 된다면 다른 트랜잭션이 드디어 알수있게 된다.
git에서는 드디어 push가 되어 git프로젝트내에 적용되여 다른 사람들도 가져가거나 볼수있게되는것이다.
고객이 택배를 받아서 승인한 상태로 더이상 취소가 불가능하며 반품이라는 기능을 사용해야한다.
EntityManager em = entityMangerFactiory.createEntityManger();
EntityTransaction transaction = em.getTransaction();
Team teamA = new Team();
teamA.setName("TeamA");
em.persist(teamA);//DB에 삽입
em.flush(teamA);//DB에 보내기 생략가능(영성속 컨텍스트에 저장된 상태)
transaction.commit()//트렌젝션을 DB에 반영, 실제 insert SQL커밋 수행
Team teamB = new Team();
teamB.setName("TeamB");
em.persist(teamB);//DB에 삽입
Member member_A = new Member();
member_A.setName("memberA");
member_A.setTeam(teamA);
em.persist(member_A);
Member findMember = em.find(Member.class, member_A.getId());
Team findTeam= findMember.getTeam();
System.out.println(findTeam.getName());
flush가 있는 경우
create member
create team
insert team // flush로 인해 쓰기지연이 발생하지 않음
insert member // flush로 인해 쓰기지연이 발생하지 않음
print "TeamA" (memberA.getTeam())
flush가 없는 경우
create member
create team
print "TeamA" (memberA.getTeam()) // 쓰기 지연이 발생하더라도 영속성 컨텍스트에서 조회해옴
insert team // 쓰기 지연이 발생한 부분
insert member // 쓰기 지연이 발생한 부분