- 시작하게 된 계기 및 다짐 😮
이번 코드스테이츠의 백엔드 엔지니어링 개발자 부트캠프
에 참여하게 되면서 현직개발자 분들의 빠른 성장을 위한 조언 중 자신만의 블로그를 이용하여 배운 것 들을 정리하는게 많은 도움이 된다 하여 시작하게 되었다.
- 학습 목표 😮
목표 | 결과 |
---|---|
JDBC가 무엇인지 이해 | O |
Java에서 JDBC가 어떤 역할을 하는지 이해할 수 있다. | O |
Spring Data JDBC가 무엇인지 이해 | O |
Spring Data JDBC를 이용해서 데이터의 저장, 수정, 조회, 삭제 작업 | O |
Spring Data JDBC 기반의 엔티티 연관 관계를 매핑 | O |
- 정리 😮
1. JDBC란
2. JDBC동작 흐름
3. JDBC API 사용 흐름
4. Connection Pool
Extra
JDBC에 대한 추가학습
인메모리(DB)
H2 콘솔 사용법
★application.properties / application.yml 추가 설정 정보들
**0. 앞으로 학습 해야할 기술들
0. Spring Data JDBC : 기본적인 ORM중심 기술로, Spring에서 Data에 접근하는 일관된 방식 제공, JPA와 마찬가지로 ORM기술을 사용하지만 기술적 복잡도를 좀 낮춰놓은 기술
1. Java Data JDBC : 비교적 쉽고 간단, 소규모 및 복잡하지 않은 프로젝트에 좋음
2. JPA : 실무에서 가장 많이 사용하고 있는 기술
3. Java Data JPA : Spring에서 JPA를 편리하게 사용할 수 있게 해주는 기술로, JPA 선행 지식이 있어야한다.
1. 데이터 엑세스 기술 유형
SQL 중심 기술
객체(Object) 중심 기술
2. Spring Data JDBC 사전 준비
1. 의존 라이브러리 추가
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-jdbc'
runtimeOnly 'com.h2database:h2' -> 인메모리 DB를 인 H2 사용
}
1. 인메모리 DB
- 일반적인 DB와 달리, 휘발성으로 애플리켄이션이 실행되는 동안에만 데이터가 저장되는 DB공간
- 개발환경에서 각 종 테스트를 진행하기 위해 이를 제외한 나머지 데이터를 제외하고 테스트하여 정확도가 올라감
- 이런 이유로, 로컬 개발환경에서는 인메모리DB를 주로 사용
spring:
h2:
console:
enabled: true
path: /h2 --> (1)
datasource:
url: jdbc:h2:mem:test --> (2)
(1) H2 콘솔의 접속 URL Context path를 간결하게 /h2로 설정
(2) JDBC URL이 매번 바뀌지 않도록 jdbc:h2:mem:test로 설정
3. Spring Data JDBD 실습 (Hello World 샘플)
CrudRepository
Spring Data JDBC 적용 순서
1). build.gradle에 사용할 데이터베이스를 위한 의존 라이브러리를 추가합니다.
2). application.yml 파일에 사용할 데이터베이스에 대한 설정을 합니다.
3). ‘schema.sql’ 파일에 필요한 테이블 스크립트를 작성합니다.
4). application.yml 파일에서 ‘schema.sql’ 파일을 읽어서 테이블을 생성할 수 있도록 초기화 설정을 추가합니다.
5). 데이터베이스의 테이블과 매핑할 엔티티(Entity) 클래스를 작성합니다.
6). 작성한 엔티티 클래스를 기반으로 데이터베이스의 작업을 처리할 Repository 인터페이스를 작성합니다.
7). 작성된 Repository 인터페이스를 서비스 클래스에서 사용할 수 있도록 DI 합니다.
8). DI 된 Repository의 메서드를 사용해서 서비스 클래스에서 데이터베이스에 CRUD 작업을 수행합니다.
4. application.yml 설정 정리
[예제 Code]
spring:
h2:
console:
enabled: true
path: /h2 # (1) Context path
datasource:
url: jdbc:h2:mem:test # (2) JDBC URL
sql:
init:
schema-locations: classpath*:db/h2/schema.sql # (3) 테이블 생성 파일 경로
data-locations: classpath*:db/h2/data.sql
logging:
level:
org:
springframework:
jdbc:
core: TRACE
(1) H2콘솔의 접속 URL Context path를 간결하게 /h2로 설정
(2) JDBC URL이 매번 바뀌지 않게 'jdbc:h2:mem:test'로 설정
1. DDD(Domain Driven Design)란?
도메인이란?
애그리거트(Aggregate)란?
애그리거트 루트 란?
2. 샘플 애플리케이션 도메인 엔티티 및 테이블 설계
Extra
1. 엔티티/테이블 설계 확인
2. Spring Data JDBC에서의 애그리거트 객체 매핑
@애너테이션
1). @Table("ORDERS")
- 정의하지 않으면, 기본적으로 클래스 이름이 테이블 이름과 매핑됨
2). @Id
- 해당 멤머변수를 식별자로 지정한다는 의미
3). @MappedCollection(idColumn = "ORDER_ID")
- 엔티티 클래스 간에 연관 관계를 맺어지게 해주는 정보
- 즉, 클래스 간의 기본키-외래키 형태로, 외래키 컬럼(idColumn)을 의미함
- 외래키가 포함된 테이블을 자식테이블이라고함
- JPA에서는 @OneToMany(mappedBy="")
애그리거트 객체 매핑 규칙
Extra
AggregateReference
@MappedCollection
0. @애너테이션
1. 리포지토리(Repository) 인터페이스
DDD에서 사용하는 언어로 JPA,JDBC에서 데이터엑세스 계층에서 DB와 상호작용을 하는 역할을 하는 인터페이스
(1) CrudRepository<엔티티클래스, 기본키 멤버변수>를 상속하여 사용
(2) 쿼리 메서드 정의를 이용한 데이터 조회 메서드 정의
‘find + By + SQL 쿼리문에서 WHERE 절의 컬럼명 + (WHERE 절 컬럼의 조건이 되는 데이터) ’
WHERE절의 조건 컬럼을 여러개 지정하고 싶다면 'And' 사용'
IF, EMAIL,NAME 컬럼을 지정하고 싶다면
[EX. findByEmailAndName(String email, String name)]처럼 사용하면 된다.
쿼리 메소드 안에는 엔티티 클래스의 멤버변수명을 적어 주어야한다.
멤버 변수의 경우, 카멜케이스(exampleCase)를 사용해야 한다.
[예제 Code]
import com.codestates.member.entity.Member;
import org.springframework.data.repository.CrudRepository;
import java.util.Optional;
// (1)
public interface MemberRepository extends CrudRepository<Member, Long> {
// (2)
Optional<Member> findByEmail(String email);
[SELECT "MEMBER"."NAME" AS "NAME", "MEMBER"."PHONE" AS "PHONE", "MEMBER"."EMAIL" AS
"EMAIL", "MEMBER"."MEMBER_ID" AS "MEMBER_ID" FROM "MEMBER" **WHERE "MEMBER"."EMAIL" = ?**]와 같음
}
2. 추가적으로 GitHub의 jdbc 템플릿 코드 확인
Extra_Optional
1. Optional.of(10);
- Optional객체를 만들어 해당 값이 10 인경우, 만일 null값이 들어가면 NullPointerException발생
2. Optional.ofNullable();
- Null이 가능
3. Optional.empty()
- 비어있는 경우로, 주로 Null값일 때 사용
4. Optional.isPresent()
- 내부에 값이 있는지 없는지 확인, 값이 있을시 True
5. Optional.isEmpty()
- 값이 비어있을 경우 True
6. Optional.get()
- 내부 값을 가져온다.
7. Optional.ifPresent(Consumer )
- Optional에 값이 있는 경우 그 값을 Consumer Functional Interface에 전달 후 로직을 수행.
8. Optional.orElse(T)
- 값이 있을 경우 가져오고 없을 경우 인자값으로 선언한 내용을 반환
9. Optional.orElseGet(Supplier)
- 값이 있으면 가져오고 없는 경우에 Supplier Functional Interface로직을 수행한다.
10. Optional.orElseThrow()
- 값이 있으면 가져오고 없으면 에러를 던진다.
11. Optional.filter(Predicate)
- Predicate Functional Interface를 수행 하여 조건에 부합하는 값을 가져온다.
12. Optional map(Function)
- Function Functional Interface를 수행하여 내부 값을 순회하며 변경한 후 반환한다.
13. Optional flatMap(Function)
- Optional 안에 들어있는 인스턴스가 Optional인 경우 내부 원소값을 꺼낼 때 사용한다.
Extra
1. Spring Data JDBC 쿼리 메서드
- https://docs.spring.io/spring-data/jdbc/docs/current/reference/html/#jdbc.query-methods
- https://docs.spring.io/spring-data/jdbc/docs/current/reference/html/#repositories.query-methods.details
2. Iterator vs Iterable 차이점
- Iterable은 필드멤버로 Iterator를 가지고있고, Iterable은 Collection(list,set등)의 상위 인터페이스이다.
- Iterable을 다운 캐스팅하여 하위 컬렉션으로 받을 수 있음
- https://devlog-wjdrbs96.tistory.com/84
1. Spring Data JDBC 기반 데이터 엑세스 계층 연동 실습
2. 페이징(Paging,Page),페이지네이션 API
0. 사진.
PagingAndSortingRepository 인터페이스
Page 도메인과 Pageable
1). Pageable
- Page의 정보들을 담고있는 객체이다.
- PageRequest(page,size,[Sort])를 통해 Pageable인터페이스를PageRequest객체로 받는다.
Sort부분 정렬의 경우 선택적이며, 자세한 사항은 인터페이스 확인(Sort.by("tet").descending()
- 이를 PagingAndSortingRepository 인터페이스의 findAll(Pageable) 메서드를 통해 Page 제네릭
객체 형태로 구현화해서 받을 수 있음
2). Page
- 실제 리소스를 가지고 있는 객체로, Content안에 domain이 담겨있다.
- Slice<>인터페이스를 상속하며, PageImpl 구현 클래스를 통해 생성
- getContent()를 통해 값들을 가져올 수 있으며, 그 밖에 여러 메서드들이 있음
- https://ithub.tistory.com/28 확인 or 직접확인
3. Comparator 구현
[예제 Code]
Collections.sort(list, new Comparator<User>() {
public int compare(User o1, User o2) {
if(o1.getNo()>o2.getNo()) {
return -1;
}else if(o1.getNo()<o2.getNo()) {
return 1;
}else {
return 0;
}
}
});
- 피드백 😮
Spring Data JDBC를 이용하여 엔티티, 리포지토리를 설계하고 이를 기반으로 실습을 하였다.
리포지토리의 경우, CrudRepository<Entity, Type>을 상속받아 DB에 접근하는 쿼리문을 자동으로 떤져주는 리포지토리 인터페이스를 만들어 이를 사용하였다.
- 앞으로 해야 될 것 😮