mojo's Blog

JPA 시작 본문

JPA

JPA 시작

_mojo_ 2022. 8. 1. 20:25

새로운 프로젝트를 만들어본다.

 

 

위와 같이 설정하였다.

그리고 pom.xml 으로 와서 다음과 같이 작성하였다.

 

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>jpa-basic</groupId>
    <artifactId>ex1-hello-jpa</artifactId>
    <version>1.0.0</version>

    <properties>
        <maven.compiler.source>11</maven.compiler.source>
        <maven.compiler.target>11</maven.compiler.target>
    </properties>

    <dependencies>
        <!-- JPA 하이버네이트 -->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-entitymanager</artifactId>
            <version>5.3.10.Final</version>
        </dependency>

        <!-- H2 데이터베이스 -->
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <version>1.4.199</version>
        </dependency>
    </dependencies>

</project>

 

H2 데이터베이스의 버젼은 1.4.199 으로 설치하였다.

dependency 에서 version 을 동일하게 설정해야 한다.

 

 

※ JPA 설정하기 - persistence.xml

 

JPA 설정 파일을 /META-INF/persistence.xml 에 위치시켜야 한다.

 

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.2"
             xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_2.xsd">

    <persistence-unit name="hello">
        <properties>
            <!-- 필수 속성 -->
            <property name="javax.persistence.jdbc.driver" value="org.h2.Driver"/>
            <property name="javax.persistence.jdbc.user" value="sa"/>             
            <property name="javax.persistence.jdbc.password" value=""/>
            <property name="javax.persistence.jdbc.url" value="jdbc:h2:tcp://localhost/~/test"/>             
            <property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect"/>
            <!-- 옵션 -->
            <property name="hibernate.show_sql" value="true"/>
            <property name="hibernate.format_sql" value="true"/>
            <property name="hibernate.use_sql_comments" value="true"/>
            <!--<property name="hibernate.hbm2ddl.auto" value="create" />-->
        </properties>
    </persistence-unit>
</persistence>

 

여기서 필수 속성의 user, password, url 을 잘 설정해야 한다.

 

 

h2 database 에서 설정된 JDBC URL, 사용자명, 비밀번호가 동일해야 한다.

 

 

그리고 H2Dialect 를 사용하기 때문에 dialect 의 값은 H2Dialect 임을 알 수 있다.

 

 

※ JPA 구동 방식

 

 

이제 자바 파일을 생성해서 제대로 설정이 완료되었는지 테스트해본다.

 

 

package hellojpa;

public class JpaMain {

    public static void main(String[] args) {

    }
}

 

 

성공적으로 실행되었다!

이번엔 persistence.xml 에서 persistence-unit name = "hello" 를 가지고 다음과 같이 코드를 작성한 후

실행해본다.

 

 

public class JpaMain {

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

 

 

뭔가 이상한 오류가 출력된다. 

하지만 오류가 나오는게 정상이다.

 

이번엔 H2 콘솔로 이동하여 Member 테이블을 생성해보도록 하자.

 

 

다시 돌아와서 Member 클래스를 생성하여 다음과 같이 작성한다.

@Entity
public class Member {
    
    @Id
    private Long id;
    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 가 로딩될 때 해당 애너테이션을 통해 인식할 수 있기 때문에 꼭 넣어줘야 한다.

@Id : primary key 임을 애너테이션을 달아줘서 인식할 수 있다. 

 

이제 데이터를 진짜 넣어보도록 한다.

public class JpaMain {

    public static void main(String[] args) {
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
        EntityManager em = emf.createEntityManager();
        EntityTransaction tx = em.getTransaction();

        tx.begin();

        Member member = new Member();

        member.setId(2L);
        member.setName("헬로우");

        em.persist(member);

        tx.commit();
        em.close();
        emf.close();
    }
}

 

 

잘 들어갔다.

 

이번엔 예외 처리를 통해 데이터를 삽입하는 코드를 작성해보자.

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 {
            Member member = new Member();
            member.setId(3L);
            member.setName("HI BYE");

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

 

 

예외가 발생한 경우 rollback 처리를 해준다.

 

이번엔 데이터를 찾는 코드를 작성해보도록 하자.

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 {
            Member findMember = em.find(Member.class, 1L);
            System.out.println("findMember.id = " + findMember.getId());
            System.out.println("findMember.name = " + findMember.getName());
            tx.commit();
        } catch(Exception e) {
            tx.rollback();
        } finally {
            em.close();
        }
        emf.close();
    }
}

 

 

정상적으로 id 에 해당하는 name 을 가져오는 것을 확인할 수 있다.

 

이번엔 데이터를 삭제하는 코드를 작성해보도록 하자.

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 {
            Member findMember = em.find(Member.class, 1L);
            em.remove(findMember);
            tx.commit();
        } catch(Exception e) {
            tx.rollback();
        } finally {
            em.close();
        }
        emf.close();
    }
}

 

 

정상적으로 삭제되는 것을 알 수 있다.

 

이번엔 id 가 2인 멤버의 이름을 변경하는 코드를 작성해보도록 하자.

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 {
            Member findMember = em.find(Member.class, 2L);
            findMember.setName("HelloJPA");
            tx.commit();
        } catch(Exception e) {
            tx.rollback();
        } finally {
            em.close();
        }
        emf.close();
    }
}

 

 

정상적으로 변경된 것을 알 수 있다.

persist 없이 setName 만으로 update 가 실행된다는 것이 핵심이다.

 

 

★ 주의

엔티티 매니저 팩토리는 하나만 생성해서 애플리케이션 전체에서 공유한다.

엔티티 매니저는 쓰레드간에 공유하지 않는다. (사용하고 버려야 함)

JPA 의 모든 데이터 변경은 트랜잭션 안에서 실행한다.

 

이번엔 모든 멤버들을 출력해보는 코드를 작성해보도록 하자.

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 {
            List<Member> result = em.createQuery("select m from member as m", Member.class)
                    .getResultList();

            for (Member member : result) {
                System.out.println("Member.name = " + member.getName());
            }
            tx.commit();
        } catch(Exception e) {
            tx.rollback();
        } finally {
            em.close();
        }
        emf.close();
    }
}

 

 

정상적으로 모든 멤버를 출력한 것을 확인할 수 있다.

 

 

※ JPQL

 

JPA 를 사용하면 엔티티 객체를 중심으로 개발

문제는 검색 쿼리이다.

검색을 할 때도 테이블이 아닌 엔티티 객체를 대상으로 검색한다.

모든 DB 데이터를 객체로 변환해서 검색하는 것은 불가능하다.

애플리케이션이 필요한 데이터만 DB 에서 불러오려면 결국 검색 조건이 필요한 SQL 이 필요하다.

 

JPA 는 SQL 을 추상화한 JPQL 이라는 객체 지향 쿼리 언어를 제공한다.SQL 과 문법이 유사하다. (SELECT, FROM, WHERE, GROUP BY, HAVING, JOIN 지원)JPQL 은 엔티티 객체를 대상으로 쿼리한다.SQL 은 데이터베이스 테이블을 대상으로 쿼리한다.

 

테이블이 아닌 객체를 대상으로 검색하는 객체 지향 쿼리이다.

SQL 을 추상화해서 특정 데이터베이스 SQL 에 의존하지 않는다.

JPQL 을 한마디로 정의하면 객체 지향 SQL 이다.

 

'JPA' 카테고리의 다른 글

다양한 연관관계 매핑  (0) 2022.08.10
연관관계 매핑 기초  (0) 2022.08.10
엔티티 매핑  (0) 2022.08.09
영속성 관리 - 내부 동작 방식  (0) 2022.08.08
JPA 이란  (0) 2022.08.01
Comments