인프런 올인원 자바 스프링 강의를 학습 목적으로 정리하여 포스팅합니다.
section4. 생애 최초 JPA 사용하기
23강. 문자열 SQL을 직접 사용하는 것이 너무 어렵다!!
1. 문자열 SQL을 직접 사용하는 것이은 어렵다
SQL을 직접 작성하면 생기는 단점
1. 문자열을 작성하기 때문에 실수가 있을 수 있고, 실수를 인지하는 것이 느리다.
ex) "SELEC * FRO user WHER id = ?";
컴파일 시점에 발견되지 않고, 런타임 시점에 발견된다.
2. 특정 데이터베이스에 종속적이게 된다.
3. 반복 작업이 많아진다. 테이블을 하나 만들 때마다 CRUD 쿼리가 항상 필요하다.
4. 데이터베이스의 테이블과 객체는 패러다임이 다르다. ex) 연관 관계, 상속
JPA (Java Persistence API)
= 자바 진영의 ORM (Object-Relational Mapping)
* Persistence = 영속성 = 서버가 재시작되어도 데이터는 영구적으로 저장되는 속성
* API : 정해진 규칙
* Relational = 관계형 DB에 테이블
* Mapping = 둘을 짝짓는다
즉, JPA란
객체와 관계형 DB의 테이블을 짝지어
데이터를 영구적으로 저장할 수 있도록 정해진 Java 진영의 규칙
HIBERNATE
JPA는 규칙일 뿐 코드로 작성되어 있는 것은 아니다.
JPA를 코드로 구현한 것이 HIBERNATE이다.
HIBERNATE는 내부적으로 JDBC를 사용한다.
2. 유저 테이블에 대응되는 Entity Class 만들기
JPA 어노테이션
@Entity
: 스프링이 User 객체와 user 테이블을 같은 것으로 본다.
* Entity : 저장되고, 관리되어야 하는 데이터
@Id
: 이 필드를 primary key로 간주한다.
@GeneratedValue(strategy = GenerationType.~~)
: primary key는 DB에서 자동 생성해주기 때문에 이 어노테이션을 붙여주어야 한다.
DB의 종류마다 자동 생성 전략이 다른데, MySQL의 경우 auto_increment는 IDENTITY 전략이다.
@Column
: 객체의 필드와 Table의 필드를 매핑한다. 서로 동일할 경우 생략이 가능하다.
ex) @Column(nullable = false, length = 20, name = "name") == name varchar(20)
JPA를 사용하기 위해서는 기본 생성자가 꼭 필요하다.
protected로 생성해도 된다.
최초 JPA 적용 시 applcation.yml에 작성해야 할 것
spring:
jpa:
hibernate:
ddl-auto: none
properties:
hibernate:
show_sql: true
format_sql: true
dialect: org.hibernate.dialect.MySQL8Dialect
ddl-auto: none ㅡ> 스프링이 시작할 때 DB에 있는 테이블을 어떻게 처리할지
create : 기존 테이블이 있다면 삭제 후 다시 생성
create-drop : 스프링이 종료될 때 테이블을 모두 제거
update : 객체와 테이블이 다른 부분만 변경
validate : 객체와 테이블이 동일한지 확인
none
show_sql : true ㅡ> JPA를 사용해 DB에 SQL을 날릴 때 SQL을 보여줄 것인지
format_sql: true ㅡ> SQL을 보여줄 때 예쁘게 포맷팅 할 것인지
dialect ㅡ> 이 옵션으로 DB를 특정하면 조금씩 다른 SQL을 수정해준다.
3. Spring Data JPA를 이용해 자동으로 쿼리 날리기
SQL을 작성하지 않아도 동작하는 이유
Sping Data JPA :
복잡한 JPA 코드를 스프링과 함께 쉽게 사용할 수 있도록 도와주는 라이브러리
즉, Spring Data JPA는 JPA를 사용하고, JPA는 Hibernate로 구현되어 있고, Hibernate는 내부적으로 JDBC를 사용하고 있다.
4. Spring Data JPA를 이용해 다양한 쿼리 작성하기
제공하는 기능들 중
- save : 주어지는 객체를 저장하거나 업데이트 시켜준다 = INSERT 기능
- findAll : 주어지는 객체가 매핑된 테이블의 모든 데이터를 가져온다.
- findById : id를 기준으로 특정한 1개의 데이터를 가져온다. = select * from user where id = ?;
- delete : 주어지는 데이터를 DB에서 제거한다 = DELETE 기능
Spring Data JPA의 추가적인 쿼리 작성법
함수 이름만 잘 작성하면, 알아서 SQL이 조립되어 원하는 기능을 만들 수도 있다!
예를 들어 findByName이라고 이름을 지으면
- find 라고 작성하게 되면, 1개의 데이터를 가져온다.
- By 뒤에 붙는 필드 이름으로 SELECT 쿼리의 WHERE 문이 작성된다.
- 예를 들어, findByName은 selet * from user where name = ? 이 된다.
1. By 앞에 들어갈 수 있는 구절
- find : 1건을 가져온다. 반환 타입은 객체가 될 수도 있고, Optional<타입> 이 될 수도 있다.
- findAll : 쿼리의 결과물이 N개인 경우 사용한다. List<타입> 반환한다.
- exists : 쿼리 결과가 존재하는 지 확인한다. 반환 타입은 boolean 이다.
- count : SQL의 결과 개수를 센다. 반환 타입은 long 이다.
2. By 뒤에 들어갈 수 있는 구절
각 구절은 And 나 Or로 조합할 수도 있다. ex) findAllByNameAndAge
- GreaterThan : 초과
- GreaterThanEqual : 이상
- LessThan : 미만
- LessThanEqual : 이하
- Between : 사이에
- StartsWith : ~로 시작하는
- EndsWith : ~로 끝나는
5. 트랜잭션 이론편
트랜잭션
쪼갤 수 없는 업무의 최소 단위
모든 SQL을 성공시키거나, 하나라도 실패하면 모두 실패시키기 위한 단위
start transaction; // 트랜잭션 시작하기
commit; // 트랜잭션 정상 종료하기 즉, SQL 반영
rollback; // 트랜잭션 실패 처리하기 즉, SQL 미반영
6. 트랜잭션 적용과 영속성 컨텍스트
@Transactional 을 붙여 트랜잭션을 적용시킨다.
💥 스프링프레임워크 안에 있는 어노테이션으로 적용시켜야 한다.
IOException과 같은 Checked Exception은 롤백이 일어나지 않는다.
SELECT 쿼리만 사용한다면 readOnly 옵션을 쓸 수 있다.
약간의 성능적 이점이 있다.
영속성 컨텍스트
테이블과 매핑된 Entity 객체를 관리/보관하는 역할
스프링에서는 트랜잭션을 사용하면 영속성 컨텍스트가 생겨나고,
트랜잭션이 종료되면 영속성 컨텍스트가 종료된다.
- 변경 감지 (Dirty Check) : 영속성 컨텍스트 안에서 불러와진 Entity는 명시적으로 save하지 않더라도, 변경을 감지해 자동으로 저장된다.
- 쓰기 지연 : DB의 INSERT / UPDATE / DELETE SQL을 바로 날리는 것이 아니라, 트랜잭션이 commit 될 때 모아서 한 번만 날린다.
- 1차 캐싱 : ID를 기준으로 Entity를 기억한다. 캐싱된 객체는 완전히 동일하다.
'JAVA > [인프런] 스프링 강의들' 카테고리의 다른 글
[ 서버 개발 올인원 패키지] 6. 생애 최초 배포 준비하기 (0) | 2023.03.09 |
---|---|
[ 서버 개발 올인원 패키지] 5. 책 요구사항 구현하기 (0) | 2023.02.26 |
[ 서버 개발 올인원 패키지] 3. 역할의 분리와 스프링 컨테이너 (0) | 2023.02.22 |
[ 서버 개발 올인원 패키지] 2. 생애 최초 Database 조작하기 (0) | 2023.02.22 |
[ 서버 개발 올인원 패키지] 1. 생애 최초 API 만들기 (0) | 2023.02.19 |