ㅇ 장점
- 객체 지향적인 코드로 인해 더 직관적이고 비즈니스 로직에 더 집중할 수 있다.
- ORM을 이용하면 SQL Query가 아닌 직관적인 코드로 데이터를 조작할 수 있어 개발자가 객체 모델로 프로그래밍 하는데 도움을 준다.
- 선언문, 할당, 종료 같은 부수적인 코드가 없거나 줄어듬
- 코드 재사용, 유지보수 편리
- DBMS 종속성이 줄어듬
- 종속적이지 않다는것은 구현 방법 뿐만아니라 많은 솔루션에서 자료형 타입까지 유효함
- DBMS를 교체하는 거대한 작업에도 비교적 적은 리시크와 시간 소요
- 객체 간의 관계를 바탕으로 SQL 자동생성하기 떄문에 RDBMS의 데이터 구조와 Java의 객체지향 모델 사이의 간격 좁힘
ㅇ 단점
- N + 1 문제
- 생성되는 쿼리 속도의 저하, 성능 저하

JPA를 사용하는 이유는 반복적인 CRUD SQL을 처리해주며 개발자가 어떤 SQL이 실행되는지 생각만하면되고 예측도 쉽게 가능하다.
JPA랑 Spring Data JPA는 차이가 있다.

스프링에서 흔히 사용하는 JPA는 JPA를 이용하는 Spring Data Jpa 프레임워크이지 JPA는 아니다.

JPA는 실행 시 한 DB당 하나의 EntityManagerFactory를 생성하고 WAS가 종료되는 시점에 EntityManagerFactory도 사라집니다.
고객의 요청이 들어온다면 하나의 스레드를 생성하여 EntityManager를 만들고 Transaction이 종료되면 해당 스레드를 종료합니다.
📌 엔티티 매니저 팩토리는 스레드를 세이프하기떄문에 여러 스레드가 동시 접근이 가능하지만 EntityManager는 스레드가 동시에 접근하면 동시성 문제가 발생하기 때문에 공유가 안된다.
비영속 : 영속성 컨텍스트와 관계 X 영속 : 영속성 컨텍스트에 저장 준영속 : 영속성 컨텍스트에 저장되어있다가 분리 삭제 : 삭제된 상태
Flush
동작 과정
변경을 감지 -> 수정된 Entity를 쓰기 지연 SQL 저장소에 등록 -> 쓰기 지연 SQL 저장소의 쿼리를 DB에 전송
연관 관계 매핑 방법
객체 연관관계 vs 테이블 연관관계
1, 테이블은 외래키를 이용해 연관관계 설정
2, 객체는 참조를 이용해 연관관계 설정
3, 테이블 연관관계는 항상 양방향
4, 객체 연관관계는 항상 단반향이지만 우리가 양방향이라고 말하는 것은 사실 두개의 단방향 연관관계를 뜻함
- 연관관계의 주인
ㅇ 양방향 연관관계는 단방향 연관관계 두개를 말하는 것이다.
연관관계의 주인이라고 한다.
ㅇ @ManyToOne ( N : 1 )
ㅇ @OneToMany ( 1 : N )
ㅇ @OneToOne ( 1 : 1 )
ㅇ @ManyTOMany ( N : M )
ㅇ 프록시 (proxy)
1, 프록시 특징
ㅇ 즉시 로딩과 지연 로딩의 차이점
즉시 로딩 : 엔티티를 조회할 때 연관된 모든 엔티티도 함께 조회
지연 로딩 : 연관된 엔티티를 실제 사용할 때 조회 ( 프록시 조회
JPQL : java persistence Query Language
Criteria 쿼리 : JPQL을 편하게 작성하도록 도와주는 API, 빌더 클래스 모음
네이티브 SQL : JPA에서 JPQL 대신 쿼리를 직접 사용 가능
QueryDSL : 쿼리처럼 JPQL을 편하게 작성하도록 도와주는 빌더 클래스, 비표준 오픈소스 프레임워크
ㅇ JPQL
String jpql= "select m From Member m where m.name like '%hello%'";
List<Member> result = em.createQuery(jpql, Member.class).getResultList();
m은 별칭이며 m.name은 entity의 객체 필드명이다.
위의 결과로 실행되는 SQL은 아래와 같다.
select
m.id as id,
m.age as age,
m.USERNAME as USERNAME,
m.TEAM_ID as TEAM_ID
from
Member m
where
m.age>18
ㅇ JPQL의 fetch 조인
SQL 조인의 종류와 다릅니다. JPQL에서는 성능 최적화를 위해 제공하는 기능이며 연관된 entity나 컬렉션을 SQL 한 번에 함께 조회하는 기능입니다.
List<Member> resultList = em.createQuery("select m from Member m join fetch m.team", Member.class).getResultList();
위와 같이 fetch 조인을 사용하여 실행한 결과 쿼리는 1개로 한번에 조회되는 것을 볼 수 있다.
Hibernate:
select
member0_.id as id1_0_0_,
team1_.team_id as team_id1_1_1_,
member0_.name as name2_0_0_,
member0_.team_id as team_id3_0_0_,
team1_.name as name2_1_1_
from
Member member0_
inner join
Team team1_
on member0_.team_id=team1_.team_id
ㅇ 네이티브 SQL
JPQL에서 지원하는 SQL을 직접 사용하는 기능
String sql = "SELECT ID, NAME FROM USER WHERE NAME = `kim`"
List<User> userList = em.createNativeQuery(sql, User.class).getResultList();
스프링 프레임 워크에서 JPA를 편리하게 사용할 수 있도록 지원한다. 데이터 접근 계층을 개발할 때 구현 클래스 없이 인터페이스만 작성한다.
List<User> findByUsername(String username);
List<User> findById(Long Id);
ㅇ @Query
@Query 어노테이션을 사용해서 리포지터리 인터페이스에 쿼리 직접 정의
@Query("SELECT user FROM User user where user.createdAt between ?1 to ?2")
List<User> getUserByCreatedAt(Date from, Date to);
데이터베이스의 상태를 변화시키기 위해서 수행하는 작업 단위를 말한다. 즉 SELECT, INSERT, DELETE, UPDATE 작업을 할 때 트랜잭션이 발생한다.
( 보통 서비스로직에서 트랜잭션이 시작되고 컨트롤러 부분에서 트랜잭션이 끝난다. )
ㅇ 스프링 컨테이너의 기본 전략

ㅇ 레이지 로딩을 사용할 경우 준영속상태 문제
ㅇ 트랜잭션의 낙관전락과 비관전락