Hibernate/JPA(EntityManager)

JPA EntityManager - Entity 기본 구현 및 SELECT, INSERT, UPDATE, DELETE

유혁스쿨 2023. 4. 15. 02:30
728x90
반응형

Entity

JPA가 관리할수 있도록 하는 자바 객체이다.

 

Member Entity Class생성

@Entity //JPA 첫로딩시 Entity로 관리할수 있도록 인식
//@Table(name = "USER") // DB에 Member라는 이름이 아닌 User라는 이름의 테이블을 설정한다면 해당 어노테이션으로 지정한다. 생략시 엔티티 클래스명으로 테이블이 관리됨.
public class Member {
    @Id
    private Long id;
//    @Column(name = "username") //DB 컬럼이 username이라면 해당 어노테이션을 통해서 Entity가 관리된다. (생략시 필드명으로 컬럼명이 관리됨)
    private String name;

    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;
    }
}

 

@Entity JPA 첫 로딩시 해당 Class를 Entity로 관리할수록 인식하는 어노테이션이다.
@Table DataBase에 Entity 클래스 이름과 다른 이름의 테이블명을 설정한다면 해당 어노테이션으로 설정한다.
테이블명은 해당 어노테이션의 name속성을 통해 명시해준다.
생략시 엔티티 클래스명으로 테이블이 관리된다.
@Id DataBase와 Entity간에 특정 컬럼을 대상으로 Primary Key를 설정하는 어노테이션이다.
@Column DataBase의 컬럼과 Entity 필드명이 일치하지 않을 경우 해당 어노테이션을 통해서 Entity가 관리된다.
name속성을 통해 원하는 컬럼명을 지정할 수 있다.
생략시 Entity 클래스에 지정한 필드명으로 DataBase 컬럼명이 관리된다.

 

 

INSERT : persist()

먼저 DB에 데이터를 INESERT 한다.

public class JpaMain {
    public static void main(String[] args) {
        // Entity Manager Factory는 애플리케이션 로딩 시점에 딱 하나만 만들어야한다.
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");

        EntityManager em = emf.createEntityManager();

        EntityTransaction tx = em.getTransaction(); //트랜잭션 생성
        tx.begin(); //트랜잭션 시작

        /* insert */
        Member member = new Member();
        member.setId(1L);
        member.setName("HelloA");
        em.persist(member); // Member가 저장된다.

        tx.commit(); // 트랜잭션 Commit

        em.close(); // 엔티티매니저 닫기.(내부적으로 DB 커넥션을 물고 동작하므로 사용후에는 꼭 닫아줘야한다)
        emf.close(); //전체 애플리케이션이 종료되면 EntityManagerFactory도 닫아줘야한다.
    }
}

 

EntityManagerFactory 객체를 생성하고 해당 객체로부터 EntityManger를 생성한다.

        // Entity Manager Factory는 애플리케이션 로딩 시점에 딱 하나만 만들어야한다.
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");

        EntityManager em = emf.createEntityManager();

 

JPA에서는 트랜잭션이라는 처리가 중요하다.

JPA에서 데이터를 변경하는 모든 작업은 꼭 Transaction 안에서 작업해야한다.

JPA라는 기술을 떠나(Mybatis등을 사용하더라도) RDB 자체적으로는 데이터 변경 자체를 트랜잭션 안에서 실행하도록 설계되어있기 때문이다.

Database에서 직접 쿼리를 날릴때에는 트랜잭션 하지않아도 INSERT, UPDATE가 작동 되던현상은 내부적으로 처리를 한다.

트랜잭션을 걸지 않더라도 DB는 내부적으로 트랜잭션개념을 가지고 있기 때문이다 (Auto Commit 등)

 

실제 DB에 저장하는 트랜잭션 단위, 예를들어 고객이 웹 애플리케이션에서 특정 행위(상품 장바구니 추가 등)를 할 때 마다 DB Connection을 얻어 Query를 날리고 종료되는 하나의 일관적인 단위의 활동을 할 때 만들어 줘야 한다.

 

따라서 아래 코드를 작성해야한다.

        EntityTransaction tx = em.getTransaction(); //트랜잭션 생성
        tx.begin(); //트랜잭션 시작

 

트랜잭션을 생성하고 시작한 이후로 Insert작업을 진행한다.

        /* inert */
        Member member = new Member();
        member.setId(1L);
        member.setName("HelloA");
        em.persist(member); // Member가 저장된다.
        
        tx.commit(); // 트랜잭션 Commit

 Member 엔티티에 값을 세팅하고 em.persist(member)를 통해 데이터베이스에 저장을 한다.

저장을 한후에 commit을 꼭 해줘야 데이터베이스에 반영된다.

        em.close(); // 엔티티매니저 닫기.(내부적으로 DB 커넥션을 물고 동작하므로 사용후에는 꼭 닫아줘야한다)
        emf.close(); //전체 애플리케이션이 종료되면 EntityManagerFactory도 닫아줘야한다.

EntityManager는 내부적으로 DB커넥션을 물고 동작하므로 commit이 완료된 후에는 꼭 엔티티 매니저를 닫아줘야 한다.

또한 전체 애플리케이션이 종료되면 EntityManagerFactory도 닫아줘야한다.

 

트랜잭션 작업도중 에러가 발생할 수 있으므로 다음과같이 TryCatch문 안에서 작업해줘야한다.

    try {
        /* insert */
        Member member = new Member();
        member.setId(1L);
        member.setName("HelloA");
        em.persist(member); // Member 저장
        tx.commit(); // 트랜잭션 커밋 - DB 반영
    } catch(Exception e) {
        tx.rollback(); // 에러발생 - 트랜잭션 롤백처리
    } finally {
        em.close(); // 엔티티매니저 닫기
    }
    emf.close(); //전체 애플리케이션이 종료되면 EntityManagerFactory도 닫아줘야한다.

SELECT : find()

        /* select */
        Member findMember = em.find(Member.class, 1L);//Member 조회
        System.out.println("findMember.getId() = " + findMember.getId());
        System.out.println("findMember.getName() = " + findMember.getName());

첫번째 매개변수에는 Entity를 클래스로 불러와 지정해주고 

두번째 매개변수에는 DB에 저장되있는 조회하고자 하는 Primary Key 값을 지정한다.

 

UPDATE

find() 작업을 통해 조회된 엔티티 객체의 값을 변경한다.

        findMember.setName("HelloJPA");

이때 저장할때 호출했던 persist를 따로 하지 않아도 수정이된다. (자바의 컬렉션을 다루는것과 유사하다)

JPA를 통해서 Entity를 가져오는 순간 부터 JPA가 관리하게 된다.

JPA는 Transaction이 Commit하는 시점에 변경 내용을 체크한다.

따라서 트랜잭션이 Commit하는 시점 즉, Commit 직전에 변경된 내용을 확인하고 엔티티에 변경된 내용이 있을 경우 Update Query를 날린 후 Commit된다.

 

DELETE : remove()

    em.remove(findMember);

삭제의 경우 remove() 메소드를 호출하여 find()하여 가져온 Entity의 내용을 삭제한다.

 

INSERT SELECT UPDATE DELETE 완성코드.

public class JpaMain {
    public static void main(String[] args) {
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");

        EntityManager em = emf.createEntityManager();

        EntityTransaction tx = em.getTransaction();
        tx.begin();


        try {
            /* INSERT */
//            Member member = new Member();
//            member.setId(1L);
//            member.setName("HelloA");
//            em.persist(member); // Member 저장

            /* SELECT */
            Member findMember = em.find(Member.class, 1L); // Member 조회
            System.out.println("findMember.getId() = " + findMember.getId());
            System.out.println("findMember.getName() = " + findMember.getName());

            /* UPDATE */
            findMember.setName("HelloJPA");

            /* DELETE */
//            em.remove(findMember);

            tx.commit(); // 트랜잭션 Commit
        } catch (Exception e) {
            tx.rollback(); // 데이터 저장시 문제 발생하면 트랜잭션 Rollback
        } finally {
            em.close(); // 엔티티매니저 닫기.(내부적으로 DB 커넥션을 물고 동작하므로 사용후에는 꼭 닫아줘야한다)
        }
        emf.close(); //전체 애플리케이션이 종료되면 EntityManagerFactory도 닫아줘야한다.
    }
}

 

 

EntityManagerFactory는 웹 서버가 올라오는 시점에 DB당 하나만 생성한다.

EntityMangerFactory는 WAS가 내려갈때 닫아줘야만 하며, 커넥션풀링등 내부적으로 사용되는 리소스가 릴리즈된다.

EntityManager는 고객의 요청이 올때마다 생성한뒤 사용하고 닫아주는것을 반복한다. 마치 DB커넥션을 사용하고 버리는것처럼 사용하고 버려야한다. (쓰레드간에 절대 공유해서 사용하면 안된다.)

 

 

 

 

 

728x90
반응형