[자바 ORM 표준 JPA] JPA 시작

[자바 ORM 표준 JPA] JPA 시작

JPA 시작하기


Hello JPA - 프로젝트 생성#


H2 Database 설치#


H2 홈페이지에서 OS에 맞는 설치 파일을 다운로드한다.

contact

C:\Program Files (x86)\H2\bin\h2.bat 실행

contact

contact

contact

contact

jdbc:h2:~/jpashop (최초 1회, 세션키 유지한 상태로 실행)

이후 부터는 jdbc:h2:tcp://localhost/~/jpashop 으로 접속

contact

http://localhost:8082/login.jsp 에서 연결버튼 클릭

contact

SpringBoot 프로젝트 생성#


contact

contact

contact

pom.xml#

hibernate와 h2database dependency 추가

contact

contact

contact

<?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>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <dependencies>
        <!-- JPA 하이버네이트 -->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-entitymanager</artifactId>
            <version>5.6.1.Final</version>
        </dependency>
        <!-- H2 데이터베이스 -->
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <version>1.4.200</version> <!-- 설치한 H2 database 버전과 동일, 202 버전 설치 하였지만 202 버전은 없어 200으로 설치 -->
        </dependency>
    </dependencies>

</project>

스프링부트에 맞는 Dependency 버전확인#


contact

contact

contact

contact

contact

JPA 설정하기 - persistence.xml#


  • JPA 설정 파일
  • /META-INF/persistence.xml 위치 /ex1-hello-jpa/src/main/resources/META-INF/persistence.xml
  • persistence-unit name으로 이름 지정
  • javax.persistence로 시작: JPA 표준 속성
  • hibernate로 시작: 하이버네이트 전용 속성

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> 

데이터베이스 방언#


SQL 표준을 지치지 않는 특정 데이터베이스의 고유한 기능

  • JPA는 특정 데이터베ㅔ이스에 종속 X
  • 각각의 데이터베이스가 제공하는 SQL 문법과 함수는 조금씩 다름 > - 가변 문자 : MySQL은 VARCHAR, Oracle은 Varchar2 > - 문자열을 자르는 함수 : SQL 표준은 SUBSTRING(), Oracle은 SUBSTR() > - 페이지 : MySQL은 LIMIT, Oracle은 ROWNUM

contact

데이터베이스 방언 옵션#

  • hibernate.dialect 속성에 지정
  • H2 : org.hibernate.dialect.H2Dialect
  • Oracle 10g : org.hibernate.dialect.Oracle10gDialect
  • MySQL : org.hibernate.dialect.MySQL5InnoDBDialect
  • 하이버네이트는 40가지 이상의 데이터베이스 방언 지원

JPA 구동 방식#


contact

실습 - JPA 동작 확인#


  • JpaMain 클래스 생성
  • JPA 동작 확인

contact

persistence.xml 설정이 잘되어 있어야 Persistence. 했을때 뜸, PersistenceUnitName은 persistence.xml에 설정된 persistence-unit의 name

<?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>
EntitiyManagerFactory 생성 후 실행#

contact

contact

JpaMain.java


package hellojpa;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

public class JpaMain {
    //psvm 단축키로 생성 가능
    public static void main(String[] args) {
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
        EntityManager em = emf.createEntityManager();

        // 실제 구현 위치
	
	   // 사용 후 닫아줘야한다 
        em.close();	
        emf.close(); 

    }
}

객체 테이블을 생성하고 매핑하기#


  • @Entity : JPA가 관리할 객체
  • @Id : 데이터베이스 PK와 패밍

Member.java

package hellojpa; 
import javax.persistence.Entity; // 비슷한게 나오면  javax 
import javax.persistence.Id; 

@Entity  // 중요
public class Member { 
 @Id 
 private Long id; 
 private String name; 
 //Getter, Setter … 
} 
create table Me

MEMBER CREATE SQL

create table Member ( 
 id bigint not null, 
 name varchar(255), 
 primary key (id) 
)
H2 Database에서 SQL 실행#

contact

Member.java 생성#

main과 같은 경로에 생성

contact

Member에 데이터 Insert#


Member.java 생성후 실행

contact

Id를 추가 하지 않았기 때문에 JPA에서 Id를 포함하라고 오류를 발생

contact

Exception in thread "main" javax.persistence.PersistenceException: org.hibernate.id.IdentifierGenerationException: ids for this class must be manually assigned before calling save(): hellojpa.Member
	at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:154)
	at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:181)
	at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:188)
	at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:807)
	at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:785)
	at hellojpa.JpaMain.main(JpaMain.java:16)
Caused by: org.hibernate.id.IdentifierGenerationException: ids for this class must be manually assigned before calling save(): hellojpa.Member
	at org.hibernate.id.Assigned.generate(Assigned.java:33)
	at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:119)
	at org.hibernate.event.internal.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:192)
	at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:135)
	at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:62)
	at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:800)
	... 2 more

JpaMain.java - member.id, memeber.name 세팅

package hellojpa;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

public class JpaMain {
    //psvm 단축키로 생성 가능
    public static void main(String[] args) {
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
        EntityManager em = emf.createEntityManager();

        Member member = new Member();

        member.setId(1L);
        member.setName("홍길동");

        em.persist(member);

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

    }

}

하지만 그래도 오류가 발생..

"C:\Program Files\Java\jdk1.8.0_271\bin\java.exe" "-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2021.2.3\lib\idea_rt.jar=52200:C:\Program Files\JetBrains\IntelliJ IDEA 2021.2.3\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.8.0_271\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_271\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_271\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_271\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_271\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_271\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_271\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_271\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_271\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_271\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_271\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_271\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_271\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_271\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_271\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_271\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_271\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_271\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_271\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_271\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_271\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_271\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_271\jre\lib\rt.jar;C:\develop\Git\jpa-basic\ex1-hello-jpa\target\classes;C:\Users\offetuoso\.m2\repository\org\hibernate\hibernate-entitymanager\5.3.10.Final\hibernate-entitymanager-5.3.10.Final.jar;C:\Users\offetuoso\.m2\repository\org\jboss\logging\jboss-logging\3.3.2.Final\jboss-logging-3.3.2.Final.jar;C:\Users\offetuoso\.m2\repository\org\hibernate\hibernate-core\5.3.10.Final\hibernate-core-5.3.10.Final.jar;C:\Users\offetuoso\.m2\repository\org\javassist\javassist\3.23.2-GA\javassist-3.23.2-GA.jar;C:\Users\offetuoso\.m2\repository\antlr\antlr\2.7.7\antlr-2.7.7.jar;C:\Users\offetuoso\.m2\repository\org\jboss\jandex\2.0.5.Final\jandex-2.0.5.Final.jar;C:\Users\offetuoso\.m2\repository\com\fasterxml\classmate\1.3.4\classmate-1.3.4.jar;C:\Users\offetuoso\.m2\repository\javax\activation\javax.activation-api\1.2.0\javax.activation-api-1.2.0.jar;C:\Users\offetuoso\.m2\repository\org\dom4j\dom4j\2.1.1\dom4j-2.1.1.jar;C:\Users\offetuoso\.m2\repository\org\hibernate\common\hibernate-commons-annotations\5.0.4.Final\hibernate-commons-annotations-5.0.4.Final.jar;C:\Users\offetuoso\.m2\repository\javax\persistence\javax.persistence-api\2.2\javax.persistence-api-2.2.jar;C:\Users\offetuoso\.m2\repository\net\bytebuddy\byte-buddy\1.9.5\byte-buddy-1.9.5.jar;C:\Users\offetuoso\.m2\repository\org\jboss\spec\javax\transaction\jboss-transaction-api_1.2_spec\1.1.1.Final\jboss-transaction-api_1.2_spec-1.1.1.Final.jar;C:\Users\offetuoso\.m2\repository\com\h2database\h2\1.4.200\h2-1.4.200.jar" hellojpa.JpaMain
12월 19, 2021 9:58:07 오후 org.hibernate.jpa.internal.util.LogHelper logPersistenceUnitInformation
INFO: HHH000204: Processing PersistenceUnitInfo [
	name: hello
	...]
12월 19, 2021 9:58:07 오후 org.hibernate.Version logVersion
INFO: HHH000412: Hibernate Core {5.3.10.Final}
12월 19, 2021 9:58:07 오후 org.hibernate.cfg.Environment <clinit>
INFO: HHH000206: hibernate.properties not found
12월 19, 2021 9:58:08 오후 org.hibernate.annotations.common.reflection.java.JavaReflectionManager <clinit>
INFO: HCANN000001: Hibernate Commons Annotations {5.0.4.Final}
12월 19, 2021 9:58:09 오후 org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl configure
WARN: HHH10001002: Using Hibernate built-in connection pool (not for production use!)
12월 19, 2021 9:58:09 오후 org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH10001005: using driver [org.h2.Driver] at URL [jdbc:h2:tcp://localhost/~/test]
12월 19, 2021 9:58:09 오후 org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH10001001: Connection properties: {user=sa}
12월 19, 2021 9:58:09 오후 org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH10001003: Autocommit mode: false
12월 19, 2021 9:58:09 오후 org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl$PooledConnections <init>
INFO: HHH000115: Hibernate connection pool size: 20 (min=1)
12월 19, 2021 9:58:09 오후 org.hibernate.dialect.Dialect <init>
INFO: HHH000400: Using dialect: org.hibernate.dialect.H2Dialect
12월 19, 2021 9:58:10 오후 org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl stop
INFO: HHH10001008: Cleaning up connection pool [jdbc:h2:tcp://localhost/~/test]

Process finished with exit code 0

JPA에서는 Transaction이 매우 중요한데, JPA의 모든 작업은 Transaction 안에서 이루어져야한다.

EntityTransaction 추가#

JpaMain.java

package hellojpa;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;

public class JpaMain {
    //psvm 단축키로 생성 가능
    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(1L);
        member.setName("홍길동");

        em.persist(member);

        tx.commit(); // 트랜잭션 커밋

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

    }
}

Transaction을 추가후 실행

contact

contact

persistence.xml 옵션 설명

 	<property name="hibernate.show_sql" value="true"/>  <!-- 실행 sql 로깅 -->
	<property name="hibernate.format_sql" value="true"/>  <!-- 실행 sql 포메팅 -->
	
	<!-- /* insert hellojpa.Member */ JPA가 Inser 를 해서 이 쿼리가 나왔다는 것을 주석으로 설명 -->
	<property name="hibernate.use_sql_comments" value="true"/>

그래고 H2 DataBase에 어떠한 테이블로 저장하겠다 설정을 하지 않았지만, 관례에 따라 @Entity의 Class명에 Insert 합니다. 또한 테이블 명을 지정하고 싶다면 @Table(name = “테이블명”)을 이용해 저장될 테이블을 세팅할 수 있습니다.
그리고 @Column(name=“컬럼명”)을 통해 저장할 컬럼을 매핑 할 수도 있습니다.

Member.java


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

    @Id
    private Long id;
    
    @Column(name="name")
    private String name;

그리고 문제가 있을때를 대비해서 Try Catch문도 포함해 줍니다.

JpaMain.java

package hellojpa;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;

public class JpaMain {
    //psvm 단축키로 생성 가능
    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(1L);
            member.setName("홍길동");
            em.persist(member);
            tx.commit();
            
            em.find(Member.class, 1L);
            
            
        }catch (Exception e){
            tx.rollback();
        }finally {
            em.close();
        }
        emf.close();
        
    }
}

Member 데이터 Select#


JpaMain.java

package hellojpa;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;

public class JpaMain {
    //psvm 단축키로 생성 가능
    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(1L);
            member.setName("홍길동");

            em.persist(member);
            tx.commit();
            */
            
            Member findMember = em.find(Member.class, 1L);

            System.out.println("findMember.id = " + findMember.getId());
            System.out.println("findMember.name = " + findMember.getName());


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

    }
}

Member 데이터 Update#


JpaMain.java

package hellojpa;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;

public class JpaMain {
    //psvm 단축키로 생성 가능
    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(1L);
            member.setName("홍길동");

            em.persist(member);
            tx.commit();
            */
            
            Member findMember = em.find(Member.class, 1L);

            System.out.println("findMember.id = " + findMember.getId());
            System.out.println("findMember.name = " + findMember.getName());

            findMember.setName("김철수");
            tx.commit();

            System.out.println("findMember.id = " + findMember.getId());
            System.out.println("findMember.name = " + findMember.getName());


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

    }
}

contact

변경된 것을 확인 할 수 있습니다. commit을 할때 set()을 통해 변경사항이 있는경우 JPA가 자동으로 Update를 해준다.

주의#


  • 엔티티 매니저 팩토리는 하나만 생성해서 애플리케이션 전체에서 공유
  • 엔티티 매니저는 쓰레드간 공유하면 절대 안됨 (사용하고 버려야한다.)
  • JPA는 모든 데이터 변경은 트랜잭션 안에서 실행

JPQL 소개#


간단 조회는 키값을 넣고 findMember하고 데이터 불러다 사용하면 되는데, 조건을 사용한 검색을 해야할때 어떻게 해야할까?
나이가 18살 이상인 회원을 모두 검색하고 싶다면?

  • 가장 단순한 조회 방법 > - EntityManager.find() > - 객체 그래프 탐색 (a.getB().getC())

실습 - JPQL 소개#


  • JPQL로 전체 회원 검색
  • JPQL로 ID가 2개 이상인 회원만 검색
  • JPQL로 이름이 같은 회원만 검색
  • JPQL에 대해 자세한 내용은 객체지향 쿼리에서 학습

실습#

JpaMain.java

package hellojpa;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
import java.util.List;

public class JpaMain {
    //psvm 단축키로 생성 가능
    public static void main(String[] args) {
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
        EntityManager em = emf.createEntityManager();
        EntityTransaction tx = em.getTransaction();

        tx.begin();

        try{
            List<Member > resultList =  em.createQuery("select m from Member as m", Member.class).getResultList();

            for(Member member :  resultList){
                System.out.println("member.name  = " + member.getName());
            }

            /*
            // Insert
            member.setId(1L);
            member.setName("홍길동");

            em.persist(member);
            tx.commit();
            */

            /*
            // Select
            Member findMember = em.find(Member.class, 1L);


            System.out.println(findMember.getId());
            System.out.println(findMember.getName());
            */

            /*
            //Update
            findMember.setName("김철수");
            tx.commit();

            System.out.println(findMember.getId());
            System.out.println(findMember.getName());
            */

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

    }
}


결과#
Hibernate: 
    /* select
        m  -- member 엔티티
    from
        Member as m */ select
            member0_.id as id1_0_,
            member0_.name as name2_0_ 
        from
            Member member0_
member.name  = 김철수

추가로 페이징을 추가할 경우

package hellojpa;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
import java.util.List;

public class JpaMain {
    //psvm 단축키로 생성 가능
    public static void main(String[] args) {
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
        EntityManager em = emf.createEntityManager();
        EntityTransaction tx = em.getTransaction();

        tx.begin();

        try{
            List<Member > resultList =  em.createQuery("select m from Member as m", Member.class)
                    .setFirstResult(1) // 로우 1 부터
                    .setMaxResults(8)	 // 로우 8 까지
                    .getResultList();

            for(Member member :  resultList ){
                System.out.println("member.name  = " + member.getName());
            }

            /*
            // Insert
            member.setId(1L);
            member.setName("홍길동");

            em.persist(member);
            tx.commit();
            */

            /*
            // Select
            Member findMember = em.find(Member.class, 1L);


            System.out.println(findMember.getId());
            System.out.println(findMember.getName());
            */

            /*
            //Update
            findMember.setName("김철수");
            tx.commit();

            System.out.println(findMember.getId());
            System.out.println(findMember.getName());
            */

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

    }
}

페이징 추가 결과#
Hibernate: 
    /* select
        m 
    from
        Member as m */ select
            member0_.id as id1_0_,
            member0_.name as name2_0_ 
        from
            Member member0_ limit ? offset ?

H2 SQL로 결과가 나오지만, persistence.xml의 hibernate.dialect를 오라클로 변경하면

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.Oracle8iDialect"/>

            <!-- 옵션 -->
            <property name="hibernate.show_sql" value="true"/>  <!-- 실행 sql 로깅 -->
            <property name="hibernate.format_sql" value="true"/>  <!-- 실행 sql 포메팅 -->

            <!-- /* insert hellojpa.Member */ JPA가 Inser 를 해서 이 쿼리가 나왔다는 것을 주석으로 설명 -->
            <property name="hibernate.use_sql_comments" value="true"/>

            <!--<property name="hibernate.hbm2ddl.auto" value="create" />-->
        </properties>
    </persistence-unit>
</persistence>
결과#

oracle 방언으로 변경된 SQL이 나온다.

Hibernate: 
    /* select
        m 
    from
        Member as m */ select
            * 
        from
            ( select
                row_.*,
                rownum rownum_ 
            from
                ( select
                    member0_.id as id1_0_,
                    member0_.name as name2_0_ 
                from
                    Member member0_ ) row_ ) 
            where
                rownum_ <= ? 
                and rownum_ > ?

JPQL#


  • JPA를 사용하면, 엔티티 객체를 중심으로 개발
  • 문제는 검색 쿼리
  • 검색을 할 때에도 테이블이 아닌 엔티티 객체를 대상으로 검색
  • 모든 DB 데이터를 객체로 변환해서 검색하는 것은 불가능
  • 애플리케이션이 필요한 데이터만 DB에서 불러오려면 결국 검색 조건이 포함된 SQL이 필요

JPQL#


  • JPA는 SQL을 추상화한 JPQL이라는 객체 지향 쿼리 언어 제공
  • SQL과 문법 유사, Select, From, Where, Group By, Having, Join 지원
  • JPQL은 엔티티 객체를 대상으로 쿼리
  • SQL을 추상화해서 특정 데이터베이스 SQL에 의존X
  • 테이블이 아닌 객체를 대상으로 검색하는 객체 지향쿼리
  • JPQL을 한마디로 정의하면 객체 지향 SQL <–> SQL은 데이터베이스 테이블 대상으로 쿼리

참고#