
도메인 주도 설계의 영향을 받은 프레임워크
시스템을 구성하는 객체들에게 적절한 책임을 할당하는 것
객체의 연관 관계에는 방향성이 있다
테이블의 연관 관계에는 방향성이 없다
객체는 자유롭게 객체 그래프를 탐색할 수 있어야 한다
JDBCTemplate, Mybatis => SQL Mapper
새로운 필드가 추가되면 SQL을 다 수정해야 한다.
99개 바꿨는데 1개를 못 바꿨다면 ? 장애 발생 !
SQL Mapper로 만들어진 코드를 까봐야지만 믿고 사용할 수 있다.
남이 만든 DAO의 메소드를 사용했더니 일부 데이터가 없는 경험 !
객체 지향 패러다임과 RDBMS 패러다임을 중간에서 번역해주는 것
자바 진영의 ORM 표준은 JPA => 즉 인터페이스, API
자바 퍼시스턴스 api -> 자카르타 퍼시스턴스 api
hibernate가 유명한 이유는 스프링 JPA의 구현체이기 때문입니당
따지자면 JPA == hibernate라고 봐도 무방
spring.jpa.hibernate.ddl-auto = create
create, create-drop, update, validate, none
프로덕션 환경에서는 create, create-drop을 사용하면 ...안된다.
실제로 validate, none을 사용하는 것이 맞음
어노테이션 기반으로 생성한다. @Entity, @Table, @Id ...
엔티티를 영구 저장하는 환경
엔티티 매니저가 영속성 컨텍스트에서 엔티티를 관리함
영속성 컨텍스트는 hashmap과 비슷하게 생겼다.
key는 엔티티의 @Id값, value는 엔티티가 들어있다.
1차 캐시에 데이터가 있으면 1차 캐시에서 조회하고,
없으면 DB에서 조회해서 1차 캐시에 저장 후 반환한다.
따라서 영속성 컨텍스트에서는 키값이 같은 엔티티가 2개 이상 존재할 수 없다.
트랜잭션이 열리고, 트랜잭션이 닫힐 때까지
영속성 컨텍스트는 트랜잭션과 운명 공동체다 !
Station station1 = station.save(new Station("잠실역"));
Station station2 = station.findByName("잠실역");
station1 == station2 // true
한 번에 쿼리가 나간다.
모아서 flush되는 순간 방출
save() 할 때 insert 쿼리는 모아두고 엔티티를 1차 캐시에 저장
commit되는 시점에 모아둔 쿼리들을 flush
@GeneratedValue를 통해 ID를 자동 생성하는 경우 ID 값을 얻어오기 위해 데이터베이스에 insert 쿼리를 날린다.
save메소드에서는 isNew일 경우에 persist, 아니면 merge를 실행하는데 isNew의 판별 기준이 id == null 이다.
persist가 실행되면 인자로 받아온 엔티티를 그대로 리턴한다.
merge가 실행되면 인자로 받아온 엔티티가 리턴되지 않을 수도 있다.
그럼 실제 엔티티의 주소값이 달라진다.
따라서 save를 실행한다면 그 리턴값을 엔티티에 저장하는 것이 안전하다.
Id를 지정한 상태에서 select 쿼리를 안 나가게 하려면 엔티티를 Persistable 인터페이스 구현체로 만들고 isNew를 오버라이드하면 된다.
영속성 컨텍스트에는 스냅샷 기능이 있어서 commit하기 전 달라진 점이 있으면 update 쿼리를 실행한다.
final Station station1 = stations.save(new Station("잠실역"));
station1.changeName("신도림역");
final Station station2 = stations.findByName("신도림역");
assertThat(station2).isNotNull(); // pass
findByName 처럼 id 기반 조회가 아닌 쿼리를 JPQL이라고 한다.
영속성 컨텍스트를 거치지 않고 바로 데이터베이스를 조회한다.
JPQL이 작동하는 순간에는 무조건 flush를 날린다.
@ManyToOne의 기본 fetchType은 EAGER
@OneToMany의 기본 fetchType은 LAZY
fetchType이 LAZY인 경우 실제 항목을 사용할 때 select 쿼리가 나간다.
디버거 동작시에도 쿼리가 실행될 수 있으니 참고
엔티티 사용 방식에 따라 fetchType을 LAZY로 변경하면 성능 이점을 얻을수도
비영속
영속
준영속
삭제
단방향, 양방향
엄밀히 말하면 객체에는 양방향 연관관계가 없다. 서로 다른 단방향 연관관계 2개가 양방향인 것처럼 보이게 할 뿐이다.
연관 관계의 주인은 비즈니스 중요도로 판별하는 것이 아니다.
게시글과 댓글은 비즈니스 중요도로 게시글이 주인인 것 같지만 댓글이 연관 관계의 주인이다. 주인만이 연관 관계와 매핑되고 외래 키를 등록, 수정, 삭제 할 수 있다.
주인이 아닌 쪽은 읽기만 가능함. 주인이 아닌 곳에서 등록/수정/삭제 해도 엔티티의 연관 관계에 영향을 미치지 않는다.
다대일 일대다 관계에서는 다쪽이 외래키를 갖는다.