인프런/자바 ORM 표준 JPA 프로그래밍 - 기본편

2) 프로젝트설정,jpa 기초

backend dev 2024. 5. 20.

 

maven

 

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

 

 

 

 

persistence.xml

<?xml version="1.0" encoding="UTF-8"?>
<!--2.2는 jpa버전이라 생각하면 된다.-->
<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">
<!--    jpa 이름 같은거 설정하는 부분 .-->
    <persistence-unit name="hello">
        <properties>
            <!-- 필수 속성 jpa는 데이터베이스에 접근해야하므로 데이터베이스 접근 정보가 필수다.  -->
            <property name="jakarta.persistence.jdbc.driver" value="org.h2.Driver"/>
            <property name="jakarta.persistence.jdbc.user" value="sa"/>
            <property name="jakarta.persistence.jdbc.password" value="123"/>
            <property name="jakarta.persistence.jdbc.url" value="jdbc:h2:tcp://localhost/~/jpa123"/>
            <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>

 

 

 

위치는 반드시 저곳에다가.

 

 

jpa는 데이터베이스가 바뀌더라도 잘동작한다. persistence.xml에서 수정하면된다.

 

dialect == 방언 // jpa는 데이터베이스가 바뀌어도 동작한다. 다음과 같은 dialect가 이미 만들어져있기 때문

 

 

 

 

 

persistence가 persistence.xml을 읽어서 entitymanagerFactory라는 클래스를 생성한다.
그다음 필요할때마다 entityManager를 생성한다.

 

 


Hello JPA - 애플리케이션 개발

 

 

객체와 테이블 만들고 매핑하기

 

테이블생성

create table Member (
 id bigint not null,
 name varchar(255),
 primary key (id)
);

 

public class JpaMain {

    public static void main(String[] args) {

        //persistence 는 persistence.xml 의 정보를 통해서 EntityManagerFactory 를 생성한다.
        //persistenceUnitName 은 아까 persistence.xml 에서 설정했던 그 이름.
        //EntityManagerFactory 는 어플리케이션 로딩시점에 단 하나만 생성된다.
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
        EntityManager em = emf.createEntityManager(); // EntityManagerFactory 를 이용해서 EntityManager 를 생성한다.

        //EntityManager 를 꺼낸후 이제 db 에 저장한다던지 조회한다던지를 진행한다.
        //하나의 트랜잭션 단위가 실행될때마다 하나의 EntityManager 가 생성되야한다. [ EntityManager 가 간단하게 하나의 데이터베이스 커넥션이라고 생각하면된다.]

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

        Member member = new Member();
        member.setId(1L);
        member.setName("HelloA");

        em.persist(member);

        tx.commit(); // 커밋

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

 

 

/**/은 주석부분이고 뒤에보면 sql문이있다.

 

persistence.xml에서 

<!-- 옵션 -->
<property name="hibernate.show_sql" value="true"/>
<property name="hibernate.format_sql" value="true"/>
<property name="hibernate.use_sql_comments"  value="true"/>

다음과 같은 설정을 했기에 sql문이 보인다.

 

데이터가 저장된것을 확인가능

 

따로 sql문을 작성하지않았는데도 db에 데이터가 생성된것을 볼 수 있다.

@Entity // jpa 가 관리해야하는 객체라는것을 알리는 어노테이션
@Getter
@Setter
@Table(name = "USER")
public class Member {

 

@Table 어노테이션으로 해당 클래스가 데이터베이스의 어떤 테이블과 매핑인지 설정할 수 있다.

없다면  클래스이름으로 찾아서 매핑한다.

 

@Column(name = "username")
private String name;

 

필드 또한 해당 테이블의 컬럼과 매핑되어야하는데
@Column 어노테이션을 이용하여 이 필드가 어떤 컬럼에 매핑되어야하는지 지정해줄수도있고
설정해주지않았다면 기본적으로 필드명과 동일한 컬럼명과 매핑한다.

 

 

 

+

원래대로 라면 다음과 같이 진행해야한다.
에러가 발생했을때 entitymanager를 닫아줘야하므로

try {
    Member member = new Member();
    member.setId(1L);
    member.setName("HelloA");
    em.persist(member);
    tx.commit(); // 커밋
}catch (Exception e) {
    tx.rollback();
}finally {
    em.close();
}
emf.close();

 

 

조회

        try {
            Member findMember = em.find(Member.class, 1L);
            System.out.println(findMember.getId());
            System.out.println(findMember.getName());

            tx.commit(); // 커밋
        }catch (Exception e) {
            tx.rollback();
        }finally {
            em.close();
        }
        emf.close();

 

수정

       try {
            Member findMember = em.find(Member.class, 1L);
            findMember.setName("HelloJPA"); //데이터를 수정해도 em.persist(findMember) 이런것을 하지않아도 된다.
            tx.commit(); // 커밋
        }catch (Exception e) {
            tx.rollback();
        }finally {
            em.close();
        }
        emf.close();

마치 자바 컬렉션에서 수정하는것처럼 하면 알아서 수정된다.

jpa를 통해서 엔티티를 가져오면 jpa가 관리를 한다.

트랜잭션을 commit하는 시점에 엔티티의 수정이 있었는지 체크를 한다.

내용의 바뀐점이 있다면 update 쿼리를 만들어서 실행한다.

그리고 커밋한다.

 

조회 - JPQL

 

        try {
//            Member findMember = em.find(Member.class, 1L);

            // jpa 는 테이블을 대상으로 쿼리를 짜지않는다. 아래의 쿼리는 멤버 객체를 대상으로 쿼리를 짠것이다. // 모든 멤버 객체를 다 가져오는 쿼리
            List<Member> result = em.createQuery("select m from Member as m", Member.class).getResultList();

            for (Member member : result) {
                System.out.println("member = " + member.toString());
            }

            tx.commit(); // 커밋
        }catch (Exception e) {
            tx.rollback();
        }finally {
            em.close();
        }
        emf.close();

 

실제 생성된 sql 쿼리를 보면 멤버의 모든 컬럼을 다 가져오는 select문이다.

 

 
List<Member> result = em.createQuery("select m from Member as m", Member.class)
        .setFirstResult(1)
        .setMaxResults(3)
        .getResultList();

이런식으로 페이징도 쉽게된다.

 

페이징 관련된 sql문이 생성된것을 확인가능 // dialect를 오라클로 바꾸면 rownum~ 이런 코드가 나왔을것이다.
오라클로 바꾸었을시

jpql은 객체를 대상으로하는 객체지향 쿼리이다.

설정된 방언(dialect)에 맞춰서 sql 쿼리를 짜준다.

 

그래서 테이블에 종속되지않고 객체에 종속되는 쿼리를 제공해준다. == jpql

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

댓글