인프런 김영한 강의 정리/자바 ORM 표준 JPA 프로그래밍 기본편

JPA 기본 | 회원관리 예제(회원등록, 조회, 수정, 삭제)

백엔드 개발자 - 젤리곰 2024. 6. 8. 21:32
728x90

1. JPA 기본 애노테이션

@Entity 

JPA가 관리하는 엔티티 클래스에 붙여주는 어노테이션!

데이터베이스 테이블과 자바 클래스 간의 매핑을 정의한다.

 

@id

Primary Key(PK)에 붙여주는 어노테이션

 

@Table(name ="")

클래스명과 테이블명이 다를때, 테이블 명을 명시해준다.

 

@Column(name="")

필드명과 테이블 컬럼명이 다를 때, 컬럼명을 명시해준다.

 

2. JPA 예시 코드 (스프링부트 없이)

⭐참고로 스프링부트 없이 JPA를 공부하고 있고, lombok라이브러리도 안쓰고 있다.

 

1) 회원등록

✅JPA 실행부

package hellojpa;

import jakarta.persistence.*;

public class JpaMain {

    public static void main(String[] args) {

        EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
        EntityManager em = emf.createEntityManager();

        //JPA는 트랜잭션이 중요하다.
        EntityTransaction tx = em.getTransaction();
        tx.begin();
        try{
            Member member = new Member();
            member.setId(1L);
            member.setName("ururuwave");

            em.persist(member);
            tx.commit();
        }catch (Exception e){
            tx.rollback();
        }finally {
            em.close();
        }

        emf.close();
    }
}

 

✅Member 테이블과 매핑되는 member 객체

package hellojpa;

import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Table;


@Entity
@Table(name="member")
public class Member {

    @Id
    private Long id;
    private String name;

//Getter와 Setter
    public void setId(Long id) {
        this.id = id;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Long getId() {
        return id;
    }

    public String getName() {
        return name;
    }
}

 

2) 회원조회

✅JPA 실행부

package hellojpa;

import jakarta.persistence.*;

public class JpaMain {

    public static void main(String[] args) {

        EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
        EntityManager em = emf.createEntityManager();



        //JPA는 트랜잭션이 중요하다.
        EntityTransaction tx = em.getTransaction();
        tx.begin();
        try{
            Member findMember = em.find(Member.class, 1L);
            System.out.println("findMember.getId() = " + findMember.getId());
            System.out.println("findMember.getName() = " + findMember.getName());
            tx.commit();
        }catch (Exception e){
            tx.rollback();
        }finally {
            em.close();
        }


        //
        em.close();
        emf.close();
    }
}

 

💡분명 테이블에 member를 insert했는데 조회를 했더니 아무 값도 없다면? 설정파일을 수정하자. 

JPA의 기본 설정에서는 애플리케이션이 시작될 때 데이터베이스 스키마를 생성하거나 초기화하는 작업을 수행한다.

스키마를 유지하려면 'update'로 설정되어있어야한다.

persistence.xml 설정파일로 가서 "create"로 되어있던 것을 "update"로 바꿔줬다.

<property name="hibernate.hbm2ddl.auto" value="update" />

🤔처음에 조회를 할때, 아무 값도 없어서 헤맸는데 이 설정 때문이었다.

Hibernate: 
    select
        m1_0.id,
        m1_0.name 
    from
        member m1_0 
    where
        m1_0.id=?
findMember.getId() = 1
findMember.getName() = ururuwave

이제 조회 성공!

 

3) 회원 수정

✅JPA 실행부

package hellojpa;

import jakarta.persistence.*;

public class JpaMain {

    public static void main(String[] args) {

        EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
        EntityManager em = emf.createEntityManager();



        //JPA는 트랜잭션이 중요하다.
        EntityTransaction tx = em.getTransaction();
        tx.begin();
        try{
            Member findMember = em.find(Member.class, 1L);
            findMember.setName("Hello,Ururuwave"); //회원 수정

            tx.commit();
        }catch (Exception e){
            tx.rollback();
        }finally {
            em.close();
        }


        //
        em.close();
        emf.close();
    }
}

회원을 찾은 다음에, 그 회원에 setName을 해주면 된다.

조회를 해보면 수정이 잘 된것을 볼 수 있다.

 

4) 회원 삭제

✅JPA 실행부

package hellojpa;

import jakarta.persistence.*;

public class JpaMain {

    public static void main(String[] args) {

        EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
        EntityManager em = emf.createEntityManager();



        //JPA는 트랜잭션이 중요하다.
        EntityTransaction tx = em.getTransaction();
        tx.begin();
        try{
            Member findMember = em.find(Member.class, 1L);
            em.remove(findMember); //EntityManager에 remove메서드 이용

            tx.commit();
        }catch (Exception e){
            tx.rollback();
        }finally {
            em.close();
        }


        //
        em.close();
        emf.close();
    }
}

멤버를 찾고, em.remove(찾은멤버)를 하면 삭제가 된다.

 

콘솔 확인

Hibernate: 
    select
        m1_0.id,
        m1_0.name 
    from
        member m1_0 
    where
        m1_0.id=?
Hibernate: 
    /* delete for hellojpa.Member */delete 
    from
        member 
    where
        id=?

selec쿼리와 delete쿼리가 잘 돌아간 것을 볼 수 있다.

 

3. 스프링부트와 함께 쓰는 JPA 코드

 

🤔나는 스프링부트를 쓸 건데!!스프링부트에서는 JPA를 어떤 구조로 쓰게 될까?

스프링부트 환경이고 사용자에게 form형식으로 정보를 받아서 member 테이블에 저장하고 member를 조회하는 상황이라고 가정해보자.

 

✅애플리케이션 실행부

package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class TestApplication {

    public static void main(String[] args) {
        SpringApplication.run(TestApplication.class, args);
    }
}

기존 실행부에 비해 아주 간단해졌다.

main에서 애플리케이션을 실행해주기만 하면 된다.

 

✅Member 엔티티 클래스

package com.example.demo.entity;

import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;

@Entity
public class Member {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;

    // Getters and Setters
    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

 

@GeneratedValue(strategy = GenerationType.IDENTITY)

-> id는 자동으로 1씩 증가하도록 했다.

나머지 Getter, Setter를 만들어줬다.

롬복 라이브러리를 쓰면 @Getter, @Setter 어노테이션만 클래스 위에 붙여주면 된다.

 

✅MemberRepository 인터페이스

package com.example.demo.repository;

import com.example.demo.entity.Member;
import org.springframework.data.jpa.repository.JpaRepository;

public interface MemberRepository extends JpaRepository<Member, Long> {
}

여기는 데이터베이스와 상호작용을 하는 메서드를 넣어주면 된다.

JPA는 리포지토리 인터페이스를 통해서 CRUD연산을 자동으로 하게끔 메서드를 제공해준다.

ex) save(), findById(), findAll(), deleteById() 등

메서드 이름을 기반으로 JPA쿼리를 자동 생성할 수 있다.

 

✅MemberService 클래스

package com.example.demo.service;

import com.example.demo.entity.Member;
import com.example.demo.repository.MemberRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
public class MemberService {

    @Autowired
    private MemberRepository memberRepository;
    
//회원등록
    @Transactional
    public Member saveMember(Member member) {
        return memberRepository.save(member);
    }

//회원조회
    @Transactional
    public Member getMember(Long id) {
        return memberRepository.findById(id).orElse(null);
    }

//회원수정
    @Transactional
    public Member updateMember(Long id, Member memberDetails) {
        Member member = memberRepository.findById(id).orElseThrow(() 
        -> new RuntimeException("Member not found"));
        member.setName(memberDetails.getName());
        // 필요한 경우 다른 속성들도 업데이트
        return memberRepository.save(member);
    }

//회원삭제
    @Transactional
    public void deleteMember(Long id) {
        Member member = memberRepository.findById(id).orElseThrow(() 
        -> new RuntimeException("Member not found"));
        memberRepository.delete(member);
    }
}

✔️리포지토리의 메서드를 호출해서 비즈니스 로직을 처리한다.

그래서 MemberRepository에 별도로 메서드를 정의해주지 않아도 된다.

✔️member를 조회했더니 null이라면 람다식을 이용해서 "Member not found"라는 메시지를 보여준다.

 

 

✅MemberController 클래스

package com.example.demo.controller;

import com.example.demo.entity.Member;
import com.example.demo.service.MemberService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/members")
public class MemberController {

    @Autowired
    private MemberService memberService;

//회원등록
    @PostMapping
    public Member createMember(@RequestBody Member member) {
        return memberService.saveMember(member);
    }
//회원조회
    @GetMapping("/{id}")
    public Member getMember(@PathVariable Long id) {
        return memberService.getMember(id);
    }
//회원수정
    @PutMapping("/{id}")
    public Member updateMember(@PathVariable Long id, @RequestBody Member memberDetails) {
        return memberService.updateMember(id, memberDetails);
    }
//회원삭제
    @DeleteMapping("/{id}")
    public void deleteMember(@PathVariable Long id) {
        memberService.deleteMember(id);
    }
}

 

✔️컨트롤러 클래스에서는 MemberService클래스를 사용해서 클라이언트 요청을 처리하고  RESTful API 엔드포인트를 제공한다.

✔️회원 조회, 수정, 삭제의 엔드포인트가 같은 이유는 HTTP 메소드를 통해 다른 작업을 수행할 수 있기때문이다.

 

-

이제 프론트엔드단에서 회원가입 form을 이용해서 가입요청을 하면 POST로 /member 엔드포인트에 요청을 보내게 될 것이고, 그럼 위 코드에 따라 Member테이블에 사용자의 id와 name정보가 저장될 것이다.

 

회원 정보 조회를 할 때는 GET 메서드로 /member/{id} 엔드포인트에 요청을 보내면

DB에서 사용자의 정보를 불러올 수 있다.

 

회원 정보 조회를 할 때는 PUT 메서드로 /member/{id} 엔드포인트에 요청을 보내면

DB에서 사용자의 정보를 수정할 수 있다. (PATCH 메서드를 이용해도 된다.)

 

회원 정보 조회를 할 때는 DELETE 메서드로 /member/{id} 엔드포인트에 요청을 보내면

DB에서 사용자의 정보를 삭제할 수 있다.

728x90