[자바 ORM 표준 JPA] JPA 시작
[자바 ORM 표준 JPA] JPA 시작
JPA 시작하기
Hello JPA - 프로젝트 생성#
H2 Database 설치#
H2 홈페이지에서 OS에 맞는 설치 파일을 다운로드한다.
C:\Program Files (x86)\H2\bin\h2.bat 실행
jdbc:h2:~/jpashop (최초 1회, 세션키 유지한 상태로 실행)
이후 부터는 jdbc:h2:tcp://localhost/~/jpashop 으로 접속
http://localhost:8082/login.jsp 에서 연결버튼 클릭
SpringBoot 프로젝트 생성#
pom.xml#
hibernate와 h2database dependency 추가
<?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 버전확인#
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
데이터베이스 방언 옵션#
- hibernate.dialect 속성에 지정
- H2 : org.hibernate.dialect.H2Dialect
- Oracle 10g : org.hibernate.dialect.Oracle10gDialect
- MySQL : org.hibernate.dialect.MySQL5InnoDBDialect
- 하이버네이트는 40가지 이상의 데이터베이스 방언 지원
JPA 구동 방식#
실습 - JPA 동작 확인#
- JpaMain 클래스 생성
- JPA 동작 확인
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 생성 후 실행#
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 실행#
Member.java 생성#
main과 같은 경로에 생성
Member에 데이터 Insert#
Member.java 생성후 실행
Id를 추가 하지 않았기 때문에 JPA에서 Id를 포함하라고 오류를 발생
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을 추가후 실행
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();
}
}
변경된 것을 확인 할 수 있습니다. 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은 데이터베이스 테이블 대상으로 쿼리