-
[Spring] JPA 끝내기 - JPASpring JPA총정리 2025. 5. 2. 13:06#JPA
💡 Spring 정리: JPA
📚 JPA란 무엇인가
- 자바 객체(클래스)를 관계형 데이터베이스 테이블에 자동으로 매핑해주는 표준 API 이고, SQL없이 객체 지향적으로 데이터를 다를 수 있게 도와주는 API이다.
- JPA는 명세(Interface)에 가깝고 실제로 동작하게 해주는 것은 EclipseLink, DataNucleus, Hibernate(가장 많이 쓰임)등
있다. - 주요 기능
기능 설명 CRUD 자동화 엔티티 객체 저장, 수정, 삭제, 조회 엔티티 매핑 클래스 ↔ 테이블, 필드 ↔ 컬럼 자동 매핑 연관관계 관리 객체 참조 기반으로 조인, 관계 설정 가능 JPQL 지원 객체 기준 쿼리 사용 (SQL 아님!) 트랜잭션, 캐시 처리 성능 향상과 일관성 유지 도와줌 배경
- JDBC에서는 테이블을 SQL 문으로 직접 생성하고 조작하기 위해 SQL문을 수동으로 작성해야 했다.
- 프로젝트의 규모가 커지거나, 다수의 데이터 베이스를 사용하게 될 수록 다은과 같은 문제를 일으킨다.
1. 테이블이 늘어날수록 SQL 문 관리가 복작하다.
2. 기존 SQL의 변경도 전체 코드에 영향을 미친다.
3. 객체가 가져야 할 역활과 책인이 흐려지게 되어 , 객체지향 원칙이 무너지게 된다
이를 해결하기 위해 ORM(Object Relation Mapping)이 등장했고 이를 표준화한 API가 JPA(Java Persistence API)가 정의 되었다.
JDBC에서의 테이블 생성하기.(SQL문으로 작성)
CREATE TABLE member ( id BIGINT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(100) NOT NULL, age INT );
JPA에서 객체
@Entity @Table(name = "members") //생략 가능 class Member{ @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; private int age; }
=> JDBC와 다르게 같은 Member 테이블 생성 좀더 직관적으로 변경되었다.
@Entity : 해당 클래스가 JPA에서 관리 되는 엔티티라고 명시함. (필수)
@Table : 생략이 가능하면서 클래스명(member)이 테이블명으로 그대로 매핑한다.
DB 테이블 이름이 클래스명과 다르다면 꼭 @Table 사용
팀 작업이나 유지보수 할때 명시적으로 써두는 것이 좋다.
Spring 환경에서의 JPA 사용
이전 JDBC 코드를 JPA로 바뀔때의 코드이다.
JPA 의존성 주입
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
JPA의 Repository
public interface MemberRepository extends JpaRepository<Member, Long> { Optional<Member> findById(Long Id); }
- 추후에 JPQL 넘어가게되면 다양한 쿼리 메서드가 나오겠지만, 기본 테스트용으로 커버가 가능하다.
- JpaRepository는 제네릭으로 관리할 Entity 클래스와 ID 타입을 지정하여 사용한다.
JPA 의 Service
@Service @RequiredArgsConstructor public class MemberServiceImpl implements MemberService { private final MemberRepository memberRepository; @Transactional @Override public MemberResponseDto setMember(MemberRequestDto dto) { Member saveMember = new Member(dto); memberRepository.save(saveMember); return new MemberResponseDto(saveMember); } @Transactional(readOnly = true) @Override public MemberResponseDto getMember(Long id) { Member getMember = memberRepository.findById(id) .orElseThrow(()-> new RuntimeException("데이터가 조재하지 않습니다.")); return new MemberResponseDto(getMember); } @Transactional(readOnly = true) @Override public List<MemberResponseDto> getAllMembers() { List<Member> members = memberRepository.findAll(); return members .stream() .map(MemberResponseDto::new) .collect(Collectors.toList()); } @Transactional @Override public MemberResponseDto updateAllMember(Long id, MemberRequestDto dto) { Member getMember = memberRepository.findById(id) .orElseThrow(()-> new RuntimeException("데이터가 존재하지 않습니다.")); getMember.updateMember(dto); return new MemberResponseDto(getMember); } @Transactional @Override public MemberResponseDto updateMemberName(Long id, MemberRequestDto dto) { Member getMember = memberRepository.findById(id) .orElseThrow(()-> new RuntimeException("데이터가 조재하지 않습니다.")); getMember.updateMember(dto); return new MemberResponseDto(getMember); } @Transactional @Override public void withdrawMember(Long id) { Member getMember = memberRepository.findById(id) .orElseThrow(()-> new RuntimeException("데이터가 조재하지 않습니다.")); memberRepository.delete(getMember); //존재 체크 (명확하게 있을때만 동작할것) memberRepository.deleteById(id); // 배치 처리나 내부 로직 처럼 신경 안 써도 되는경우 (예외 처리 없음) } }
변경점
- 오타 수정
- @Transaction 추가 //CRUD에 기본 사용 한다. Read(Get)작업할때도 붙여주되 readonly를 true로 해준다.
https://note8770.tistory.com/123
[Spring] 트랜잭션
#Transaction💡 Spring 정리: Transaction📘 개념 정리🔥 Transaction트랜잭션(Transaction)은 데이터 베이스 작업의 최소 단위로 여러 개의 작업을 한 번에 처리하거나, 전부 되돌리는 단위이다. ex) 은행 이체
note8770.tistory.com
⚠️ 실수 및 주의사항
@Transactional 없이 update/delete 수행시 반영 되지 않음.
- JPA에서 변경 사항은 트랜잭션이 커밋될 때 DB에 반영된다.
- @Transactional 없이 값을 수정하면 UPDATE/DELETE가 실행되지 않는다.
✅ 그래서 Service 계층의 CUD 메서드에는 항상 @Transactional이 필요하다.
@Transactional public void deleteMember(Long id) { Member member = memberRepository.findById(id).orElseThrow(); memberRepository.delete(member); }
✨ 팁 & 인사이트
JPA의 CRUD (생성, 읽기, 업데이트, 삭제) 작업
- 저장 및 업데이트 (Save and Update)
- save(S entity):
주어진 엔티티를 저장합니다.
만약 주어진 엔티티가 새로운 경우에는 생성하고, 이미 존재하는 경우에는 업데이트합니다.
- save(S entity):
- 조회 (Read)
- findById(ID id)
주어진 ID에 해당하는 엔티티를 찾습니다. 결과는 **Optional**로 반환됩니다. - findAll()
모든 엔티티를 조회합니다. - findAll(Sort sort)
정렬 기준에 따라 모든 엔티티를 조회합니다. - findAllById(Iterable<ID> ids)
주어진 ID 목록에 해당하는 엔티티들을 조회합니다.
- findById(ID id)
- 삭제 (Delete)
- delete(T entity)
주어진 엔티티를 삭제합니다. - deleteAll(Iterable<? extends T> entities)
주어진 엔티티 컬렉션을 삭제합니다. - deleteById(ID id)
주어진 ID를 가진 엔티티를 삭제합니다. - deleteAll()
모든 엔티티를 삭제합니다.
- delete(T entity)
- 카운트 및 존재 여부 확인
- count()
엔티티의 전체 개수를 반환합니다. - existsById(ID id)
주어진 ID를 가진 엔티티의 존재 여부를 확인합니다.
- count()
'Spring JPA총정리' 카테고리의 다른 글
[Spring] JPQL 전 총 정리 문서 (1) 2025.05.07 [Spring] JPA 심화 JDBC 끝내기기 - 실습편 (0) 2025.05.01 [Spring] JPA 심화 JDBC 끝내기기 - 기초편 (0) 2025.05.01 [Spring] JPA 심화 JDBC 끝내기 -SQL (0) 2025.05.01 - 자바 객체(클래스)를 관계형 데이터베이스 테이블에 자동으로 매핑해주는 표준 API 이고, SQL없이 객체 지향적으로 데이터를 다를 수 있게 도와주는 API이다.