JPA : 자바 표준 인터페이스로 객체와 관계형 데이터베이스 사이의 매핑을 처리하는 기술이다.
주로 객체를 데이터베이스에 저장하고 검색하는 데 사용된다.
이때 데이터에 해당하는 객체를 엔티티 객체라는 것으로 다루고 JPA로 이를 DB와 연동, 관리
Spring Data JPA는 자동으로 객체를 생성하고 이를 통해서 예외 처리등을 자동으로 처리하는 인터페이스다.
@Entity // JPA를 사용하여 데이터베이스와 연동하겠다.
@Getter
@Builder
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class Board extends BaseEntity {
/* @Id는 pk(Primary Key)로 정의하는 의미
@G2neratedBalue(strategy = GenerationType.IDENTITY)
는 Mysql/MariaDB에서 auto_increment 속성부여
* */
@Id // 해당 필드(변수)가 엔티티의 주키(primary key)이다.
@GeneratedValue(strategy = GenerationType.IDENTITY) // auto_increment 속성을 부여한다.
private Long bno;
@Column(length = 500, nullable = false) // 데이터베이스의 컬럼의 길이와 null 허용 여부 설정
private String title;
@Column(length = 2000, nullable = false)
private String content;
@Column(length = 50, nullable = false)
private String writer;
public void change(String title, String content){
this.title = title;
this.content = content;
}
}
JPA를 사용하여 데이터에 해당하는 객체를 다루고 DB와 연동, 관리하기 위해서는
@Entity로 상단에 선언을 해주고, 주(기본)키로 적용하고 싶은 필드에 @Id를 해줘야한다.
즉 JPA란 데이터베이스와의 상호작용을 위한 API로, 엔티티를 통해 도메인 모델을 정의하게 된다.
JPQL이란 JPA의 일부로서 데이터베이스 쿼리를 작성할 때 사용하는 문자열 기반 쿼리 언어이다.
즉 SQL과 유사하지만 데이터베이스 테이블이 아닌 엔티티 객체에 대해 작동하며, 데이터베이스와 객체 지향 모델 간의 간극을 메우는 역할을 한다.
[영속 콘텍스트란?]
엔티티의 생명주기를 추적하고 관리하여 데이터베이스와의 상호작용을 관리한다.
- 엔티티 관리
- 엔티티 캐싱(성능 향상)
- 트랜잭션 관리
- 지연 로딩
- 동일성 보장
보통 save() 메서드는 다음과 같은 동작을 한다.
- 데이터가 담긴 객체가 영속성 콘텍스트에 이미 존재하는지 확인
- 존재하지 않는다면, 새로운 엔티티로 간주하고 저장한다. 이때 INSERT쿼리 실행
- 객체가 이미 영속성 컨텍스트에 존재한다면 해당 엔티티를 UPDATE문을 통해 갱신
[INSERT, DELETE, UPDATE 테스트]
[INSERT 테스트]
@SpringBootTest
@Log4j2
public class BoardRepositoryTests {
@Autowired
private BoardRepository boardRepository;
@Test
public void testInsert() {
IntStream.rangeClosed(1, 100).forEach(i -> {
Board board = Board.builder()
.title("title..." + i)
.content("content..." + i)
.writer("user" + (i % 10))
.build();
Board result = boardRepository.save(board); // save에서 sql의 insert, update문을 자동으로 생성해서 실행해준다.
log.info("BNO : " + result.getBno());
});
}
위의 코드와 같이 데이터베이스에 insert를 실행하는 기능은 JpaRepository의 save()로 이뤄진다.
save는 현재의 영속 컨텍스트 내에 데이터가 존재하는지 찾아보고 해당 엔티티 객체가 없으면 insert를,
존재한다면 update문을 자동으로 실행한다.
// 엔티티 저장후 안전하게 다시 조회 ------------------------------
Board savedBoard = boardRepository.save(board);
Optional<Board> result = boardRepository.findById(savedBoard.getId());
// 특정 ID 조회----------------------------------------------
Optional<Board> result = boardRepository.findById(bno);
만약 값을 안전하게 처리하고 싶다면 Optional을,
특정한 번호(Column)를 검색하고 싶다면 findById()를 사용하면 된다.
[UPDATE, DELETE 테스트]
@Test
public void testUpdate() {
Long bno = 100L;
Optional<Board> result = boardRepository.findById(bno); // Optional은 도와주는 역할
Board board = result.orElseThrow(); // 정상일 경우 board에 값을 넘겨주고 아닐경우에 대한 로직추가 가능
board.change("--update..title 100--", "--update content 100--");
----------------------------------------------------------------------
boardRepository.deleteById(bno); -> 삭제
/*
* save : pk가 테이블에 존재하지 않으면 => 삽입 => insert문
* pk 기존 데이터에 존재하면 => 수정 => update문
* */
boardRepository.save(board);
}
findById() 이용하여 내가 수정하고 싶은 번호 추출
→. orEleThrow() 메서드로 해당 값(번호)이 정상이면 board에 값 전달
→. change()를 이용하여 내가 갱신할 값 입력
→. save()를 통해 영속성 콘텍스트에 객체가 존재하는지 확인하고 UPDATE쿼리 자동생성 및 실행
→ deleteById()를 사용하면 해당 객체 삭제.
그렇다면 수정이나 삭제 시 Select문이 먼저 실행되는가
- 만약 삽입, 갱신기능을 수행하기 위해서는 영속성 컨텍스트에 엔티티 객체가 존재하는지 확인하기 때문에 save() 메서드를 통해 값이 존재한다면 UPDATE쿼리문을, 값이 없다면 INSERT쿼리문이 실행된다. → 트랜잭션
[트랜잭션이란]
데이터베이스의 상태를 바꾸는 일종의 작업 단위이다.
INSERT, DELETE, UPDATE 등의 SQL 명령문들을 통해 데이터를 바꿀 때마다 내부적으로 자동으로 Commit을 실행하여
데이터베이스에 반영하는 것이다.
정리하자면 데이터베이스에 접근할 값들을 Domain 영역에서 엔티티 객체로 만들어놨다면,
해당 객체와 데이터베이스와 매핑을 하기 위해 JPA를 이용하여 연결 및 관리를 하게 된다.
이때 연결된 객체를 SQL 쿼리문으로 수정, 삭제 같은 작업을 자동으로 처리하기 위해 JPQL을 사용하는 것이다.
이러한 구조로 애플리케이션의 데이터 접근 계층을 구성할 수 있고, 작업을 객체 지향적으로 처리할 수 있게 된다.
'스터디 > Spring Boot' 카테고리의 다른 글
RDBMS, NoSQL이란 (0) | 2024.08.16 |
---|---|
모놀리식 아키텍처 (0) | 2024.08.15 |
[Spring Boot] 스프링 부트란? (0) | 2024.05.19 |