Spring Data JPA
JPA (Java Persistence API)
ORM(Object-Relational Mapping) 기술 표준으로 사용되는 자바 인터페이스 모음
- 장점: 유지보수 용이, DBMS 종속성X
- 단점: 복잡하고 학습 어려움
- JPA Hibernate (오픈소스)
- JPA vs MyBatis (sequelize vs MySQL)
[Spring Boot] MySQL & JPA 연동 및 테스트
프로젝트에 의존성 추가
- build.gradle에 추가 후 build
- implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'mysql:mysql-connector-java'
application.properties 설정에 DB 정보 추가
server.address=localhost
server.port=8080
# MySQL 설정
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
# DB Source URL
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/sesac?useSSL=false&allowPublicKeyRetrieval=true&characterEncoding=UTF-8&serverTimezone=Asia/Seoul
spring.datasource.username=~~~
spring.datasource.password=~~~
# mysql 연동
spring.jpa.database=mysql
spring.jpa.database-platform=org.hibernate.dialect.MySQL5InnoDBDialect
#true 설정시 JPA 쿼리문 확인 가능
spring.jpa.show-sql=true
# JPA의 구현체인 Hibernate가 동작하면서 발생한 SQL의 가독성을 높여준다.
spring.jpa.properties.hibernate.format_sql=true
# DDL(Create, Alter, Drop) 정의시 DB의 고유 기능을 사용할 수 있다.
**spring.jpa.hibernate.ddl-auto=**create
데이터베이스 스키마 자동 생성 기능
- 클래스의 매핑 정보와 데이터베이스 방언을 사용하여 데이터베이스 스키마 생성
- 어플리케이션 실행 시점에 데이터베이스 테이블 자동 생성
- application.properties 에 속성 추가
- spring.jpa.hibernate.ddl-auto 속성
- create : 기존 테이블 삭제하고 새로 생성 [ DROP + CREATE ]
- create-drop : create 속성 + 어플리케이션 종료할 때 생성한 DDL 제거 [ DROP + CREATE + DROP ]
- update : DB 테이블과 엔티티(domain 패키지 파일) 매핑 정보를 비교하고 변경사항만 수정 [ ALTER + CREATE ]
- none : 자동 생성 기능을 사용하지 않음
Error
- SPRING.JPA.OPEN-IN-VIEW 로그 오류 → https://mand2.github.io/spring/spring-boot/1/
- javax cannot resolve symbol 'persistence’ → https://ottl-seo.tistory.com/entry/IntelliJ-Cannot-resolve-symbol-에러-해결
JPA Hibernate 엔티티(Entity) 매핑
/* **Hibernate Entity** : domain 패키지 내 파일 */
@Getter
@Builder // 객체 생성
@AllArgsConstructor
@NoArgsConstructor
@Table(name = "tbl_memo")
@Entity
public class Memo {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY) //MySQL의 AUTO_INCREMENT를 사용
private Long id;
@Column(length = 200, nullable = false)
private String memoText;
}
Entity 매핑 annotation
- @Entity ❗
- DB 테이블과의 매핑
- @Entity가 붙은 클래스는 JPA가 관리
- 속성
- Name : PA에서 사용할 엔티티 이름을 지정한다. (보통 default값인 클래스 이름을 사용)
- 주의사항
- 기본 생성자 필수 (JPA가 엔티티 객체 생성 시 기본 생성자를 사용하기 때문)
- final 클래스, enum, interface, inner class 에는 사용할 수 없다.
- 저장할 필드에 final 사용 불가
- **@Table**
- 엔티티와 매핑할 테이블 지정 (클래스 명과 같은 경우 생략 가능)
- 생략 시 매핑한 엔티티 이름을 테이블 이름으로 사용
- 속성
- Name : 매핑할 테이블 이름 (default. 엔티티 이름 사용)
- CataLog : catalog 기능이 있는 DB에서 catalog 를 매핑 (default. DB 명)
- Schema : schema 기능이 있는 DB에서 schema를 매핑
- uniqueConstraints : DDL 생성 시 유니크 제약조건을 만듦 스키마 자동 생성 기능을 사용해서 DDL을 만들 때만 사용
- **@Getter**
- **@Id**
- **@GeneratedValue** PK 생성 전략
- 직접 할당
- em.persist() 호출 전 어플리케이션에서 직접 식별자 값 할당
- 자동 생성
- GenerationType.**IDENTITY** 기본키 생성을 DB에 위임 (AUTO_INCREMENT)
- GenerationType.**SEQUENCE** DB SEQUENCE를 이용해서 키 생성 + @SequenceGenerator
- GenerationType.**TABLE** 키 생성 전용 테이블 사용 + @TableGenerator
- GenerationType.**AUTO**(default) JPA 구현체(Hibernate)가 생성 방식 결정
- 오라클 → SEQUENCE , MySQL→ IDENTITY
- 직접 할당
- **@Column**
- 객체 필드를 DB Column에 매핑
- 속성
- name : 필드와 매핑할 테이블 컬럼 이름 (default: 객체의 필드 이름)
- nullable (DDL) : null 값 허용 여부 (default: true)
- unique (DDL) : 유일값 제약조건
- columnDefinition (DDL) : 컬럼 정보
- Length (DDL) : 문자 길이 제약조건, String 타입에만 사용 (default: 255)
- percision , scale (DDL) : BigDemical, BigInteger 타입에서 사용
- @Transient
- 필드 매핑X
- 데이터베이스에 저장하지 않고 조회하지도 않는다.
- 객체에 임시로 어떤 값을 보관하고 싶을 때 사용
- 타입매핑 @Enumerated @Temporal @Lob
- 연관관계 매핑 @ManyToOne @JoinColumn
JPA Repository 생성
JpaRepositry
Hibernate(JPA 구현체)를 이용하기 위해 Spring Data JPA가 제공하는 API 중 가장 많이 사용되는 인터페이스
/* Spring Data **JPA Repository** */ package SeSAC.spring.study.SeSACspringstudy.repository; **import org.springframework.data.jpa.repository.JpaRepository;** import SeSAC.spring.study.SeSACspringstudy.domain.Board; **import java.util.Optional;** // **extends JpaRepository<객체, PK타입>** **public interface** SD_BoardRepository **extends JpaRepository<Board, Integer>** { Optional<Board> findByName(String name); }
- JpaRepository 상속 → SQL문 없이 CRUD 작업 가능
- 제네릭 타입 <Entity, PK 타입> 지정 → Spring Data JPA가 자동으로 스프링의 빈(bean)으로 등록
- [ 스프링이 내부적으로 인터페이스 타입에 맞는 객체를 생성해서 빈으로 등록 ]
/* 직접 만든 JPA Repository */
package SeSAC.spring.study.SeSACspringstudy.repository;
**import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Repository;**
import SeSAC.spring.study.SeSACspringstudy.domain.Board;
**import javax.persistence.*;**
import java.util.*;
**@Repository
@RequiredArgsConstructor**
**public class** JPARepository **implements BoardRepository** {
**private final EntityManager** em;
@Override
public Board save(Board board) {
this.**em.persist**(board);
return board;
}
@Override
public Optional<Board> findById(int id) {
return **Optional.empty();**
}
@Override
public Optional<Board> findByName(String name) {
return **Optional.empty();**
}
@Override
public List<Board> findAll() {
// Select * from board as b;
return **em.createQuery**("select b from Board b", Board.class)
.getResultList(); // List<Board>
}
}
테스트를 통한 CRUD 기능 확인
Create
Repository 객체의 save() 메소드를 사용
@SpringBootTest
public class MemoRepositoryTest {
@Autowired
MemoRepository memoRepository;
@Test
public void InsertDummies() {
IntStream.rangeClosed(1, 10).forEach(i -> {
Memo memo = Memo.builder()
.memoText("Sample..." + i)
.build();
//Create!
memoRepository**.save**(memo);
});
}
Read
findById()
- 해당하는 객체를 Optional 타입으로 반환
- 한번 더 결과가 존재하는지 체크
@SpringBootTest
public class MemoRepositoryTest {
@Autowired
MemoRepository memoRepository;
@Test
public void SelectDummies() {
Long id = 10L;
**Optional**<Memo> result = memoRepository**.findById(**id);
System.out.println("=============================");
if(result.isPresent()) {
Memo memo = result.get();
System.out.println(memo);
}
}
}
Update
save()
내부적으로 해당 엔티티의 @Id값이 일치하는지를 확인해서 insert 혹은 update 작업을 처리
- JPA는 엔티티 객체들을 메모리상에 보관하려고 하기 때문에
- 특정한 엔티티 객체가 존재하는지 확인하는 select가 먼저 실행되고
- 해당 @Id를 가진 엔티티 객체가 있다면 update, 그렇지 않다면 insert 실행
@SpringBootTest
public class MemoRepositoryTest {
@Autowired
MemoRepository memoRepository;
@Test
public void UpdateDummies() {
Memo memo = Memo.builder()
.id(10L)
.memoText("Update Text")
.build();
memoRepository**.save**(memo);
}
Delete
- 수정 작업과 동일한 개념으로 삭제하려는 엔티티 객체가 있는지 먼저 확인하고, 삭제
Spring Data JPA
JPA (Java Persistence API)
ORM(Object-Relational Mapping) 기술 표준으로 사용되는 자바 인터페이스 모음
- 장점: 유지보수 용이, DBMS 종속성X
- 단점: 복잡하고 학습 어려움
- JPA Hibernate (오픈소스)
- JPA vs MyBatis (sequelize vs MySQL)
[Spring Boot] MySQL & JPA 연동 및 테스트
프로젝트에 의존성 추가
- build.gradle에 추가 후 build
- implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'mysql:mysql-connector-java'
application.properties 설정에 DB 정보 추가
server.address=localhost
server.port=8080
# MySQL 설정
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
# DB Source URL
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/sesac?useSSL=false&allowPublicKeyRetrieval=true&characterEncoding=UTF-8&serverTimezone=Asia/Seoul
spring.datasource.username=~~~
spring.datasource.password=~~~
# mysql 연동
spring.jpa.database=mysql
spring.jpa.database-platform=org.hibernate.dialect.MySQL5InnoDBDialect
#true 설정시 JPA 쿼리문 확인 가능
spring.jpa.show-sql=true
# JPA의 구현체인 Hibernate가 동작하면서 발생한 SQL의 가독성을 높여준다.
spring.jpa.properties.hibernate.format_sql=true
# DDL(Create, Alter, Drop) 정의시 DB의 고유 기능을 사용할 수 있다.
**spring.jpa.hibernate.ddl-auto=**create
데이터베이스 스키마 자동 생성 기능
- 클래스의 매핑 정보와 데이터베이스 방언을 사용하여 데이터베이스 스키마 생성
- 어플리케이션 실행 시점에 데이터베이스 테이블 자동 생성
- application.properties 에 속성 추가
- spring.jpa.hibernate.ddl-auto 속성
- create : 기존 테이블 삭제하고 새로 생성 [ DROP + CREATE ]
- create-drop : create 속성 + 어플리케이션 종료할 때 생성한 DDL 제거 [ DROP + CREATE + DROP ]
- update : DB 테이블과 엔티티(domain 패키지 파일) 매핑 정보를 비교하고 변경사항만 수정 [ ALTER + CREATE ]
- none : 자동 생성 기능을 사용하지 않음
Error
- SPRING.JPA.OPEN-IN-VIEW 로그 오류 → https://mand2.github.io/spring/spring-boot/1/
- javax cannot resolve symbol 'persistence’ → https://ottl-seo.tistory.com/entry/IntelliJ-Cannot-resolve-symbol-에러-해결
JPA Hibernate 엔티티(Entity) 매핑
/* **Hibernate Entity** : domain 패키지 내 파일 */
@Getter
@Builder // 객체 생성
@AllArgsConstructor
@NoArgsConstructor
@Table(name = "tbl_memo")
@Entity
public class Memo {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY) //MySQL의 AUTO_INCREMENT를 사용
private Long id;
@Column(length = 200, nullable = false)
private String memoText;
}
Entity 매핑 annotation
- **@Entity** ❗
- DB 테이블과의 매핑
- @Entity가 붙은 클래스는 JPA가 관리
- 속성
- Name : PA에서 사용할 엔티티 이름을 지정한다. (보통 default값인 클래스 이름을 사용)
- 주의사항
- 기본 생성자 필수 (JPA가 엔티티 객체 생성 시 기본 생성자를 사용하기 때문)
- final 클래스, enum, interface, inner class 에는 사용할 수 없다.
- 저장할 필드에 final 사용 불가
- **@Table**
- 엔티티와 매핑할 테이블 지정 (클래스 명과 같은 경우 생략 가능)
- 생략 시 매핑한 엔티티 이름을 테이블 이름으로 사용
- 속성
- Name : 매핑할 테이블 이름 (default. 엔티티 이름 사용)
- CataLog : catalog 기능이 있는 DB에서 catalog 를 매핑 (default. DB 명)
- Schema : schema 기능이 있는 DB에서 schema를 매핑
- uniqueConstraints : DDL 생성 시 유니크 제약조건을 만듦 스키마 자동 생성 기능을 사용해서 DDL을 만들 때만 사용
- **@Getter**
- **@Id**
- **@GeneratedValue** PK 생성 전략
- 직접 할당
- em.persist() 호출 전 어플리케이션에서 직접 식별자 값 할당
- 자동 생성
- GenerationType.**IDENTITY** 기본키 생성을 DB에 위임 (AUTO_INCREMENT)
- GenerationType.**SEQUENCE** DB SEQUENCE를 이용해서 키 생성 + @SequenceGenerator
- GenerationType.**TABLE** 키 생성 전용 테이블 사용 + @TableGenerator
- GenerationType.**AUTO**(default) JPA 구현체(Hibernate)가 생성 방식 결정
- 오라클 → SEQUENCE , MySQL→ IDENTITY
- 직접 할당
- **@Column**
- 객체 필드를 DB Column에 매핑
- 속성
- name : 필드와 매핑할 테이블 컬럼 이름 (default: 객체의 필드 이름)
- nullable (DDL) : null 값 허용 여부 (default: true)
- unique (DDL) : 유일값 제약조건
- columnDefinition (DDL) : 컬럼 정보
- Length (DDL) : 문자 길이 제약조건, String 타입에만 사용 (default: 255)
- percision , scale (DDL) : BigDemical, BigInteger 타입에서 사용
- @Transient
- 필드 매핑X
- 데이터베이스에 저장하지 않고 조회하지도 않는다.
- 객체에 임시로 어떤 값을 보관하고 싶을 때 사용
- 타입매핑 @Enumerated @Temporal @Lob
- 연관관계 매핑 @ManyToOne @JoinColumn
JPA Repository 생성
JpaRepositry
Hibernate(JPA 구현체)를 이용하기 위해 Spring Data JPA가 제공하는 API 중 가장 많이 사용되는 인터페이스
/* Spring Data **JPA Repository** */ package SeSAC.spring.study.SeSACspringstudy.repository; **import org.springframework.data.jpa.repository.JpaRepository;** import SeSAC.spring.study.SeSACspringstudy.domain.Board; **import java.util.Optional;** // **extends JpaRepository<객체, PK타입>** **public interface** SD_BoardRepository **extends JpaRepository<Board, Integer>** { Optional<Board> findByName(String name); }
- JpaRepository 상속 → SQL문 없이 CRUD 작업 가능
- 제네릭 타입 <Entity, PK 타입> 지정 → Spring Data JPA가 자동으로 스프링의 빈(bean)으로 등록
- [ 스프링이 내부적으로 인터페이스 타입에 맞는 객체를 생성해서 빈으로 등록 ]
/* 직접 만든 JPA Repository */
package SeSAC.spring.study.SeSACspringstudy.repository;
**import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Repository;**
import SeSAC.spring.study.SeSACspringstudy.domain.Board;
**import javax.persistence.*;**
import java.util.*;
**@Repository
@RequiredArgsConstructor**
**public class** JPARepository **implements BoardRepository** {
**private final EntityManager** em;
@Override
public Board save(Board board) {
this.**em.persist**(board);
return board;
}
@Override
public Optional<Board> findById(int id) {
return **Optional.empty();**
}
@Override
public Optional<Board> findByName(String name) {
return **Optional.empty();**
}
@Override
public List<Board> findAll() {
// Select * from board as b;
return **em.createQuery**("select b from Board b", Board.class)
.getResultList(); // List<Board>
}
}
테스트를 통한 CRUD 기능 확인
Create
Repository 객체의 save() 메소드를 사용
@SpringBootTest
public class MemoRepositoryTest {
@Autowired
MemoRepository memoRepository;
@Test
public void InsertDummies() {
IntStream.rangeClosed(1, 10).forEach(i -> {
Memo memo = Memo.builder()
.memoText("Sample..." + i)
.build();
//Create!
memoRepository**.save**(memo);
});
}
Read
findById()
- 해당하는 객체를 Optional 타입으로 반환
- 한번 더 결과가 존재하는지 체크
@SpringBootTest
public class MemoRepositoryTest {
@Autowired
MemoRepository memoRepository;
@Test
public void SelectDummies() {
Long id = 10L;
**Optional**<Memo> result = memoRepository**.findById(**id);
System.out.println("=============================");
if(result.isPresent()) {
Memo memo = result.get();
System.out.println(memo);
}
}
}
Update
save()
내부적으로 해당 엔티티의 @Id값이 일치하는지를 확인해서 insert 혹은 update 작업을 처리
- JPA는 엔티티 객체들을 메모리상에 보관하려고 하기 때문에
- 특정한 엔티티 객체가 존재하는지 확인하는 select가 먼저 실행되고
- 해당 @Id를 가진 엔티티 객체가 있다면 update, 그렇지 않다면 insert 실행
@SpringBootTest
public class MemoRepositoryTest {
@Autowired
MemoRepository memoRepository;
@Test
public void UpdateDummies() {
Memo memo = Memo.builder()
.id(10L)
.memoText("Update Text")
.build();
memoRepository**.save**(memo);
}
Delete
- 수정 작업과 동일한 개념으로 삭제하려는 엔티티 객체가 있는지 먼저 확인하고, 삭제
Spring Data JPA
JPA (Java Persistence API)
ORM(Object-Relational Mapping) 기술 표준으로 사용되는 자바 인터페이스 모음
- 장점: 유지보수 용이, DBMS 종속성X
- 단점: 복잡하고 학습 어려움
- JPA Hibernate (오픈소스)
- JPA vs MyBatis (sequelize vs MySQL)
[Spring Boot] MySQL & JPA 연동 및 테스트
프로젝트에 의존성 추가
- build.gradle에 추가 후 build
- implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'mysql:mysql-connector-java'
application.properties 설정에 DB 정보 추가
server.address=localhost
server.port=8080
# MySQL 설정
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
# DB Source URL
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/sesac?useSSL=false&allowPublicKeyRetrieval=true&characterEncoding=UTF-8&serverTimezone=Asia/Seoul
spring.datasource.username=~~~
spring.datasource.password=~~~
# mysql 연동
spring.jpa.database=mysql
spring.jpa.database-platform=org.hibernate.dialect.MySQL5InnoDBDialect
#true 설정시 JPA 쿼리문 확인 가능
spring.jpa.show-sql=true
# JPA의 구현체인 Hibernate가 동작하면서 발생한 SQL의 가독성을 높여준다.
spring.jpa.properties.hibernate.format_sql=true
# DDL(Create, Alter, Drop) 정의시 DB의 고유 기능을 사용할 수 있다.
**spring.jpa.hibernate.ddl-auto=**create
데이터베이스 스키마 자동 생성 기능
- 클래스의 매핑 정보와 데이터베이스 방언을 사용하여 데이터베이스 스키마 생성
- 어플리케이션 실행 시점에 데이터베이스 테이블 자동 생성
- application.properties 에 속성 추가
- spring.jpa.hibernate.ddl-auto 속성
- create : 기존 테이블 삭제하고 새로 생성 [ DROP + CREATE ]
- create-drop : create 속성 + 어플리케이션 종료할 때 생성한 DDL 제거 [ DROP + CREATE + DROP ]
- update : DB 테이블과 엔티티(domain 패키지 파일) 매핑 정보를 비교하고 변경사항만 수정 [ ALTER + CREATE ]
- none : 자동 생성 기능을 사용하지 않음
Error
- SPRING.JPA.OPEN-IN-VIEW 로그 오류 → https://mand2.github.io/spring/spring-boot/1/
- javax cannot resolve symbol 'persistence’ → https://ottl-seo.tistory.com/entry/IntelliJ-Cannot-resolve-symbol-에러-해결
JPA Hibernate 엔티티(Entity) 매핑
/* **Hibernate Entity** : domain 패키지 내 파일 */
@Getter
@Builder // 객체 생성
@AllArgsConstructor
@NoArgsConstructor
@Table(name = "tbl_memo")
@Entity
public class Memo {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY) //MySQL의 AUTO_INCREMENT를 사용
private Long id;
@Column(length = 200, nullable = false)
private String memoText;
}
Entity 매핑 annotation
- **@Entity** ❗
- DB 테이블과의 매핑
- @Entity가 붙은 클래스는 JPA가 관리
- 속성
- Name : PA에서 사용할 엔티티 이름을 지정한다. (보통 default값인 클래스 이름을 사용)
- 주의사항
- 기본 생성자 필수 (JPA가 엔티티 객체 생성 시 기본 생성자를 사용하기 때문)
- final 클래스, enum, interface, inner class 에는 사용할 수 없다.
- 저장할 필드에 final 사용 불가
- **@Table**
- 엔티티와 매핑할 테이블 지정 (클래스 명과 같은 경우 생략 가능)
- 생략 시 매핑한 엔티티 이름을 테이블 이름으로 사용
- 속성
- Name : 매핑할 테이블 이름 (default. 엔티티 이름 사용)
- CataLog : catalog 기능이 있는 DB에서 catalog 를 매핑 (default. DB 명)
- Schema : schema 기능이 있는 DB에서 schema를 매핑
- uniqueConstraints : DDL 생성 시 유니크 제약조건을 만듦 스키마 자동 생성 기능을 사용해서 DDL을 만들 때만 사용
- **@Getter**
- **@Id**
- **@GeneratedValue** PK 생성 전략
- 직접 할당
- em.persist() 호출 전 어플리케이션에서 직접 식별자 값 할당
- 자동 생성
- GenerationType.**IDENTITY** 기본키 생성을 DB에 위임 (AUTO_INCREMENT)
- GenerationType.**SEQUENCE** DB SEQUENCE를 이용해서 키 생성 + @SequenceGenerator
- GenerationType.**TABLE** 키 생성 전용 테이블 사용 + @TableGenerator
- GenerationType.**AUTO**(default) JPA 구현체(Hibernate)가 생성 방식 결정
- 오라클 → SEQUENCE , MySQL→ IDENTITY
- 직접 할당
- **@Column**
- 객체 필드를 DB Column에 매핑
- 속성
- name : 필드와 매핑할 테이블 컬럼 이름 (default: 객체의 필드 이름)
- nullable (DDL) : null 값 허용 여부 (default: true)
- unique (DDL) : 유일값 제약조건
- columnDefinition (DDL) : 컬럼 정보
- Length (DDL) : 문자 길이 제약조건, String 타입에만 사용 (default: 255)
- percision , scale (DDL) : BigDemical, BigInteger 타입에서 사용
- @Transient
- 필드 매핑X
- 데이터베이스에 저장하지 않고 조회하지도 않는다.
- 객체에 임시로 어떤 값을 보관하고 싶을 때 사용
- 타입매핑 @Enumerated @Temporal @Lob
- 연관관계 매핑 @ManyToOne @JoinColumn
JPA Repository 생성
JpaRepositry
Hibernate(JPA 구현체)를 이용하기 위해 Spring Data JPA가 제공하는 API 중 가장 많이 사용되는 인터페이스
/* Spring Data **JPA Repository** */ package SeSAC.spring.study.SeSACspringstudy.repository; **import org.springframework.data.jpa.repository.JpaRepository;** import SeSAC.spring.study.SeSACspringstudy.domain.Board; **import java.util.Optional;** // **extends JpaRepository<객체, PK타입>** **public interface** SD_BoardRepository **extends JpaRepository<Board, Integer>** { Optional<Board> findByName(String name); }
- JpaRepository 상속 → SQL문 없이 CRUD 작업 가능
- 제네릭 타입 <Entity, PK 타입> 지정 → Spring Data JPA가 자동으로 스프링의 빈(bean)으로 등록
- [ 스프링이 내부적으로 인터페이스 타입에 맞는 객체를 생성해서 빈으로 등록 ]
/* 직접 만든 JPA Repository */
package SeSAC.spring.study.SeSACspringstudy.repository;
**import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Repository;**
import SeSAC.spring.study.SeSACspringstudy.domain.Board;
**import javax.persistence.*;**
import java.util.*;
**@Repository
@RequiredArgsConstructor**
**public class** JPARepository **implements BoardRepository** {
**private final EntityManager** em;
@Override
public Board save(Board board) {
this.**em.persist**(board);
return board;
}
@Override
public Optional<Board> findById(int id) {
return **Optional.empty();**
}
@Override
public Optional<Board> findByName(String name) {
return **Optional.empty();**
}
@Override
public List<Board> findAll() {
// Select * from board as b;
return **em.createQuery**("select b from Board b", Board.class)
.getResultList(); // List<Board>
}
}
테스트를 통한 CRUD 기능 확인
Create
Repository 객체의 save() 메소드를 사용
@SpringBootTest
public class MemoRepositoryTest {
@Autowired
MemoRepository memoRepository;
@Test
public void InsertDummies() {
IntStream.rangeClosed(1, 10).forEach(i -> {
Memo memo = Memo.builder()
.memoText("Sample..." + i)
.build();
//Create!
memoRepository**.save**(memo);
});
}
Read
findById()
- 해당하는 객체를 Optional 타입으로 반환
- 한번 더 결과가 존재하는지 체크
@SpringBootTest
public class MemoRepositoryTest {
@Autowired
MemoRepository memoRepository;
@Test
public void SelectDummies() {
Long id = 10L;
**Optional**<Memo> result = memoRepository**.findById(**id);
System.out.println("=============================");
if(result.isPresent()) {
Memo memo = result.get();
System.out.println(memo);
}
}
}
Update
save()
내부적으로 해당 엔티티의 @Id값이 일치하는지를 확인해서 insert 혹은 update 작업을 처리
- JPA는 엔티티 객체들을 메모리상에 보관하려고 하기 때문에
- 특정한 엔티티 객체가 존재하는지 확인하는 select가 먼저 실행되고
- 해당 @Id를 가진 엔티티 객체가 있다면 update, 그렇지 않다면 insert 실행
@SpringBootTest
public class MemoRepositoryTest {
@Autowired
MemoRepository memoRepository;
@Test
public void UpdateDummies() {
Memo memo = Memo.builder()
.id(10L)
.memoText("Update Text")
.build();
memoRepository**.save**(memo);
}
Delete
- 수정 작업과 동일한 개념으로 삭제하려는 엔티티 객체가 있는지 먼저 확인하고, 삭제
'새싹🌱' 카테고리의 다른 글
TDD (0) | 2024.03.08 |
---|---|
Redux (0) | 2022.11.25 |
[JAVA] RequestMapping Handler Method (0) | 2022.11.16 |
221109 JAVA 입문 (0) | 2022.11.09 |
0907 Socket.io (0) | 2022.09.07 |