반응형
JPA 실습 복습 자료
이 문서는 제공된 학습 노트와 실습 코드를 바탕으로 JPA의 핵심 개념과 실제 구현 방법을 정리한 복습 자료입니다.
1. JPA와 ORM 기본 개념
ORM (Object-Relational Mapping)
- 정의: 객체 지향 프로그래밍의 객체와 관계형 데이터베이스의 테이블을 자동으로 매핑(연결)하는 기술입니다.
- 목적: SQL 쿼리를 직접 작성하는 대신, 자바 객체를 통해 간접적으로 데이터베이스를 조작하여 개발 편의성을 높입니다.
Hibernate
- 정의: 자바에서 ORM 기술을 구현한 대표적인 라이브러리입니다. JPA는 표준 명세(인터페이스)이고, Hibernate는 그 구현체 중 하나입니다.
JPA (Java Persistence API)
- 정의: 자바 진영의 ORM 기술 표준 API입니다. 이를 통해 개발자는 특정 ORM 구현체에 종속되지 않고 코드를 작성할 수 있습니다.
- 핵심 기능: 자바 객체(Entity)의 변경이 데이터베이스에 자동으로 반영되는 '영속성(Persistence)'을 관리합니다.
2. Entity (엔티티)
- 정의: 데이터베이스 테이블과 직접 매핑되는 자바 클래스입니다. 엔티티 클래스는 테이블의 구조를, 엔티티 객체 하나는 테이블의 레코드(행) 하나를 의미합니다.
- 주요 어노테이션:
@Entity: 해당 클래스가 DB 테이블과 매핑될 클래스임을 선언합니다.@Table(name = "테이블명"): 매핑될 테이블의 이름을 지정합니다. (생략 시 클래스명을 따름)@Id: 테이블의 기본 키(Primary Key)에 해당하는 필드를 지정합니다.@GeneratedValue(strategy = GenerationType.IDENTITY): 기본 키 값을 데이터베이스가 자동으로 생성(auto_increment)하도록 설정합니다.@Column: 필드와 테이블의 컬럼을 매핑하며, 세부 속성을 설정합니다.nullable:false로 설정 시NOT NULL제약조건unique:true로 설정 시UNIQUE제약조건length: 문자열 길이columnDefinition:TEXT,DATETIME등 컬럼 타입을 직접 정의
실습 코드 예시: GoodsEntity.java
package example2.day02;
import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Entity // 해당 클래스를 데이터베이스 테이블처럼 매핑
@Table( name = "goods" ) // 테이블 이름 정의
@Data @Builder
@NoArgsConstructor
@AllArgsConstructor
public class GoodsEntity extends BaseTime { // BaseTime 상속 (아래 Auditing 참고)
@Id // PK 필드
@GeneratedValue( strategy = GenerationType.IDENTITY ) // auto_increment
private int gno; // 제품번호
@Column( nullable = false , length = 100 ) // not null, varchar(100)
private String gname; // 제품명
@Column( nullable = true ) // null 허용
private int gprice; // 제품가격
@Column( columnDefinition = "varchar(100) default '제품설명' not null " ) // SQL 직접 작성
private String gdesc; // 제품설명
// ... toDto() 메서드 ...
}
3. Repository (리포지토리)
- 정의: 엔티티를 관리하고 데이터베이스에 대한 CRUD(Create, Read, Update, Delete) 작업을 처리하는 인터페이스입니다.
- 설정 방법:
- 인터페이스를 생성합니다.
JpaRepository<T, ID>를 상속받습니다.T: 관리할 엔티티 클래스명 (GoodsEntity)ID: 해당 엔티티의 PK 필드 타입 (Integer)
@Repository어노테이션을 추가하여 스프링 빈으로 등록합니다.
주요 기본 메서드
save(entity): 레코드 저장 (INSERT) 및 수정 (UPDATE)findAll(): 모든 레코드 조회 (SELECT *)findById(id): PK로 특정 레코드 1개 조회 (SELECT)deleteById(id): PK로 특정 레코드 삭제 (DELETE)existsById(id): PK에 해당하는 레코드 존재 여부 확인
실습 코드 예시: GoodsRepository.java
package example2.day02;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository // 빈 등록
// 지정한 엔티티들을 조작하는 인터페이스
public interface GoodsRepository
extends JpaRepository<GoodsEntity, Integer> {
// <조작할엔티티명, 엔티티PK자료형>
}
4. Service와 DTO (Data Transfer Object)
Service Layer
- 역할: 컨트롤러와 리포지토리 사이에서 비즈니스 로직을 처리합니다. 트랜잭션 관리(
@Transactional)가 주로 여기서 이루어집니다. - 엔티티 수정: JPA에서는 별도의
update메서드가 없습니다.@Transactional이 적용된 메서드 내에서 엔티티를 조회한 후, 해당 객체의setter를 호출하여 필드 값을 변경하면 트랜잭션이 커밋될 때 자동으로 UPDATE 쿼리가 실행됩니다. (이를 '더티 체킹'이라 합니다.)
DTO (Data Transfer Object)
- 필요성: 엔티티는 DB 테이블과 직접 연결되어 있어 매우 중요한 객체입니다. API 응답/요청 등 외부 계층에 엔티티를 직접 노출하는 것은 보안 및 관리상 위험할 수 있습니다. DTO는 각 계층(특히 View-Controller) 간에 데이터를 안전하게 전달하기 위한 순수 데이터 객체입니다.
- 변환:
- DTO -> Entity: 클라이언트의 요청(JSON)을 DTO로 받은 후, Service에서 이를 Entity로 변환하여 DB에 저장합니다. (
toEntity()메서드) - Entity -> DTO: Service에서 DB로부터 조회한 Entity를 DTO로 변환하여 Controller에 전달하고, 클라이언트에게 응답합니다. (
toDto()메서드)
- DTO -> Entity: 클라이언트의 요청(JSON)을 DTO로 받은 후, Service에서 이를 Entity로 변환하여 DB에 저장합니다. (
실습 코드 예시: GoodsService와 GoodsDto
GoodsDto.java (데이터 전달용 객체)
package example2.day02;
import lombok.Builder;
import lombok.Data;
@Data @Builder
public class GoodsDto {
private int gno;
private int gprice;
private String create_date;
private String update_date;
private String gname;
private String gdesc;
// DTO를 Entity로 변환 (Controller -> Service)
public GoodsEntity toEntity() {
return GoodsEntity.builder()
.gno( this.gno )
.gname( this.gname )
.gprice( this.gprice )
.gdesc( this.gdesc )
.build();
}
}
GoodsEntity.java (Entity -> DTO 변환 메서드 추가)
// ... GoodsEntity 클래스 내부 ...
// Entity를 DTO로 변환 (Service -> Controller)
public GoodsDto toDto(){
return GoodsDto.builder()
.gno( this.gno )
.gname( this.gname )
.gprice( this.gprice )
.gdesc( this.gdesc )
.update_date( this.getUpdateDate().toString() )
.create_date( this.getCreateDate().toString() )
.build();
}
GoodsService.java (비즈니스 로직)
package example2.day02;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
@Service
@Transactional
@RequiredArgsConstructor
public class GoodsService {
private final GoodsRepository goodsRepository;
// [1] 등록
public GoodsDto goodsSave(GoodsDto goodsDto) {
GoodsEntity entity = goodsDto.toEntity(); // DTO -> Entity
GoodsEntity savedEntity = goodsRepository.save( entity );
return savedEntity.toDto(); // Entity -> DTO
}
// [2] 전체조회
public List<GoodsDto> goodsFindAll() {
List<GoodsEntity> goodsEntityList = goodsRepository.findAll();
return goodsEntityList.stream()
.map(GoodsEntity::toDto) // 각 Entity를 DTO로 변환
.collect(Collectors.toList());
}
// [4] 수정 (더티 체킹 활용)
public GoodsDto goodsUpdate (GoodsDto goodsDto) {
Optional<GoodsEntity> optional = goodsRepository.findById( goodsDto.getGno());
if (optional.isPresent()) {
GoodsEntity entity = optional.get(); // 영속성 컨텍스트에 포함된 엔티티
// setter로 값만 변경하면, @Transactional에 의해 자동 UPDATE
entity.setGname(goodsDto.getGname());
entity.setGprice(goodsDto.getGprice());
entity.setGdesc(goodsDto.getGdesc());
return entity.toDto();
}
return goodsDto;
}
}
5. JPA Auditing (감시)
- 정의: 엔티티가 생성되거나 수정될 때, 생성일/수정일과 같은 필드를 자동으로 관리해주는 기능입니다.
- 설정 방법:
- 메인 클래스 활성화:
@EnableJpaAuditing어노테이션을 추가합니다. - 상속용 클래스 생성:
@MappedSuperclass를 사용하여 공통 필드를 정의할 클래스를 만듭니다. - 감시 리스너 추가:
@EntityListeners(AuditingEntityListener.class)를 상속용 클래스에 추가합니다. - 날짜 필드 매핑: 생성일 필드에
@CreatedDate, 수정일 필드에@LastModifiedDate를 추가합니다. - 엔티티에 상속: Auditing을 적용할 엔티티 클래스가 위에서 만든 상속용 클래스를
extends하도록 합니다.
- 메인 클래스 활성화:
실습 코드 예시: BaseTime.java
package example2.day02;
import jakarta.persistence.EntityListeners;
import jakarta.persistence.MappedSuperclass;
import lombok.Getter;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import java.time.LocalDateTime;
@Getter
@MappedSuperclass // 엔티티 상속용 클래스
@EntityListeners(AuditingEntityListener.class) // JPA 감시 기능 활성화
public class BaseTime {
@CreatedDate // 엔티티 생성 시 현재 날짜/시간 자동 주입
private LocalDateTime createDate;
@LastModifiedDate // 엔티티 수정 시 현재 날짜/시간 자동 주입
private LocalDateTime updateDate;
}
- 적용:
public class GoodsEntity extends BaseTime { ... }와 같이 상속받으면createDate와updateDate필드를 자동으로 관리받게 됩니다.
6. application.properties 주요 설정
JPA와 관련된 주요 설정입니다.
# JPA가 실행하는 SQL을 콘솔에 출력
spring.jpa.show-sql=true
# 콘솔에 출력되는 SQL을 보기 좋게 포맷팅
spring.jpa.properties.hibernate.format_sql=true
# 애플리케이션 실행 시 Entity와 DB 테이블 동기화 전략
# create: 기존 테이블 삭제 후 다시 생성 (테스트 환경)
# update: 변경된 스키마만 반영 (개발 환경)
# validate: Entity와 테이블이 다르면 경고 후 앱 실행 중단
# none: 아무것도 하지 않음 (운영 환경)
spring.jpa.hibernate.ddl-auto=update
# SQL의 '?' 파라미터에 바인딩되는 값을 로그로 출력
logging.level.org.hibernate.sql=DEBUG
logging.level.org.hibernate.orm.jdbc.bind=TRACE반응형
'백엔드 > 스프링' 카테고리의 다른 글
| [Spring] JPA 연관관계 및 참조 복습 (0) | 2025.11.06 |
|---|---|
| [Spring] JWT 토큰과 Security 인증 인가 로직 복습 (0) | 2025.10.22 |
| [Spring] 암호화(BCrypt) 및 쿠키(Cookie) 복습 자료 (0) | 2025.10.21 |
| [Spring] Redis 개념 및 활용법 with Spring Boot (0) | 2025.10.21 |
| [Spring] MyBatis XML 연동 개요 (0) | 2025.10.13 |
| [Spring] 도서 대여 콘셉트 트랜잭션 실습과 피드백 마크다운 (1) | 2025.09.26 |
| [Spring] 13주차+: 마이크로서비스 아키텍처(MSA) 입문 (0) | 2025.09.22 |
| [Spring] 12주차: 설정 분리 및 비동기 처리 (0) | 2025.09.22 |