쌓고 쌓다

JPA 객체 매핑과 CRUD 본문

프로그래밍/JPA

JPA 객체 매핑과 CRUD

승민아 2023. 7. 2. 17:28

회원 테이블 생성

CREATE TABLE MEMBER (
    ID VARCHAR(255) NOT NULL, -- 아이디(기본 키)
    NAME VARCHAR(255), -- 이름
    AGE INTEGER NOT NULL, -- 나이
    PRIMARY KEY(id)
);

 

회원 클래스 생성

@Entity
@Table(name="MEMBER")
public class Member {
    @Id @Column(name="id")
    private String id;

    @Column(name="name")
    private String username;
    
    private Integer age;
}

 

@Entity

이 클래스를 테이블과 매핑한다고 JPA에게 알린다.

@Entity가 붙은 클래스를 엔티티 클래스라고 한다.

 

@Table

엔티티 클래스에 매핑할 테이블 정보를 알린다.

@Table(name="member")과 같이 name 속성을 사용하여 member 테이블과 매핑한다.

이 어노테이션을 생략하면 클래스 이름을 테이블 이름으로 매핑한다.

 

@Id

엔티티 클래스의 필드를 기본 키에 매핑한다.

@Id가 사용된 필드를 식별자 필드라고 한다.

 

@Column

필드를 컬럼에 매핑한다.

여기서는 @Column(name="name")과 같이 name 속성을 사용하여

엔티티의 username 필드와 테이블의 name 컬럼을 매핑했다.

 

매핑 정보가 없는 필드

age 필드에는 매핑 정보가 없다.

매핑 어노테이션을 생략하면 필드명을 사용하여 동일한 컬럼명과 매핑한다.

필드명이 age이므로 테이블의 age 컬럼과 매핑이 된다.

 

매핑 정보

매핑 정보 회원 객체 회원 테이블
클래스와 테이블 Member MEMBER
기본 키 id ID
필드와 컬럼 username NAME
필드와 컬럼 age AGE

 

데이터베이스 방언?

JPA는 특정 DB에 종속정이지 않은 기술이라 다른 DB로 손쉽게 변경이 가능하다.

그러나 각 DB가 제공하는 SQL 문법이나 함수가 다르다.

JPA에서는 특정 데이터베이스만의 고유한 기능을 방언(Dialect)이라고 함.

이 문제를 해결하고자 JPA 구현체들은 다양한 DB 방언 클래스를 제공한다.

 

트랜잭션 관리

    public void test(){
        EntityManager em = entityManagerFactory.createEntityManager();
        EntityTransaction tx = em.getTransaction();
        try {
            tx.begin(); // 트랜잭션 시작
            logic(em); // 비즈니스 로직 실행
            tx.commit(); // 트랜잭션 커밋
        } catch(Exception e) {
            tx.rollback(); // 예외 발생 시 트랜잭션 롤백
        } finally {
            em.close();
        }
    }

JPA를 사용하려면 항상 트랜잭션 안에서 데이터를 변경해야 한다.

트랜잭션 없이 데이터를 변경하면 예외가 발생함.

 

비즈니스 로직 (logic)

    public void logic(EntityManager em){
    
    	/* 등록 */
        String id = "id1";
        Member member = new Member();
        member.setId(id);
        member.setUsername("승민");
        member.setAge(2);

        em.persist(member);

        /* 수정 */
        member.setAge(24);

        /* 한 건 조회 */
        Member findMember = em.find(Member.class, id);
        System.out.println("findMember = " + findMember.getUsername()
            + ", " + findMember.getAge());

        /* 하나 이상 조회 */
        List<Member> members = em.createQuery("SELECT m FROM Member m", Member.class)
                .getResultList();
        System.out.println(members.size());
        
        /* 삭제 */
        em.remove(member);
    }

 

1) 등록

String id = "id1";
Member member = new Member();
member.setId(id);
member.setUsername("승민");
member.setAge(2);

em.persist(member);

엔티티를 저장하려면 persist() 메소드와 저장할 엔티티를 넘겨 실행하면 된다.

메소드를 실행하면 JPA는 회원 엔티티의 매핑 정보(어노테이션)를 분석해 다음의 SQL을 생성해 DB에 전달한다.

insert into member (age,name,id) values ('id1','승민',2)

 

2) 수정

member.setAge(24);

엔티티를 수정하고 반영하려면 update() 같은 메소드를 써야할 것 같지만, 그런 메소드는 없다.

JPA는 어떤 엔티티가 변경되었는지 추적하는 기능이 있어서 단순히 엔티티의 값만 변경해 주면 UPDATE SQL을 생성해 DB에 반영한다.

update member set age=20,name='승민' where id='id1'

 

3) 삭제

em.remove(member);

엔티티를 삭제하려면 remove 메소드에 삭제하려는 엔티티를 넘겨주자.

JPA가 DELETE 쿼리를 생성해서 실행한다.

delete from member where id='id1'

 

4) 한 건 조회

Member findMember = em.find(Member.class, id);

매핑한 식별자 값으로 엔티티를 조회해 반환한다.

 

5) 하나 이상의 회원 목록 조회

List<Member> members = em.createQuery("SELECT m FROM Member m", Member.class)
	.getResultList();

 

JPA는 SQL을 추상화한 JPQL를 제공한다.

"select m from Member m"가 JPQL이다.

from Member는 회원 엔티티 객체를 말하는 거지 MEMBER 테이블이 아니다.

 

JPA는 JPQL을 분석해서 적절한 SQL을 만들어 DB에서 조회한다.

select m.id, m.name, m.age from member m
Comments