- JPA에서 제일 중요한것 객체와 테이블 정확한 매핑.
(실무에서 이게 어렵다 테이블이 수십 개)
- JPA 내부 동작 방식이 중요.
0. SQL 중심적인 개발의 문제점
- 패러다임의 불일치 (객체와 RDBMS 사이의 괴리)
- CRUD 무한 반복 (자바 객체를 SQL로, SQL을 자바로)
- 필드 추가 시 쿼리문 고쳐줘야 함.
-> 그러다보니 개발자는 객체와 RDB사이의 SQL매퍼의 일을 한다.
DB에서 객체 상속 : Table 슈퍼타입 서브타입 관계 사용하지만
- INSERT때는 쿼리를 슈퍼타입과 서브타입에 각각 넣어야한다.
- 조회떄는 JOIN SQL 작성, 객체 생성...
-> 자바 컬렉션에서는 너무 쉬움. 객체의 다형성도 활용 가능하다.
DB에서 연관 관계 : 객체는 참조를 사용하지만 테이블은 외래 키를 사용
- 객체를 테이블에 맞춰서 모델링을 해야 함(Team ID의 FK필요)
-> 객체다운 모델링은 TeamID가 아니라 Team이라는 참조, type을 가져야 함.
-> 자바 컬렉션에 관리 한다면 member를 꺼내면 getter로 team 조회가 됨.
DB에서 객체 그래프 탐색 : SQL에 따라 탐색범위가 결정 됨. (객체는 자유롭게 탐색이 된다.)
- DAO, Repository에 탐색범위에 따라서 결정 되는 것. 설정하지 않은 건 탐색이 불가능. (엔티티 신뢰 문제 발생)
-> DAO를 다 까봐야 알 수 있음.
-> 모든 객체를 미리 로딩할 수 없음. (계층 분할이 어렵다)
DB에서 비교 : SQL에 따라 새로운 인스턴스를 생성하기 때문에 같은 쿼리라고 하더라도 비교가 안됨.
-> 자바 컬렉션에서 비교를 한다면 같음 (list.get()에서 나오는 값이 같은 참조값이니까)
객체를 자바 컬렉션에 저장하듯이 DB를 사용할 수 없을까?
-> 이것의 답이 JPA임.
1. JPA란?
"Spring Data JPA, part of the larger Spring Data family, makes it easy to easily implement JPA-based (Java Persistence API) repositories. It makes it easier to build Spring-powered applications that use data access technologies.
Implementing a data access layer for an application can be quite cumbersome. Too much boilerplate code has to be written to execute the simplest queries. Add things like pagination, auditing, and other often-needed options, and you end up lost.
Spring Data JPA aims to significantly improve the implementation of data access layers by reducing the effort to the amount that’s actually needed. As a developer you write your repository interfaces using any number of techniques, and Spring will wire it up for you automatically. You can even use custom finders or query by example and Spring will write the query for you!"
Java Persistence API 로, Java의 ORM 표준 명세
Persistence란 실행프로그램이 꺼지더라도 데이터가 유지되는 성질, DB를 내포하는 것이다.
Interface이기 때문에 구현체가 필요한데, 구현체로는 hibernate, EclipseLink, DataNucleus 3개가 있고
Hibernate가 주로 사용된다.
ORM(Object Relational Mapping) : 객체 관계 매핑
JPA의 동작 :Application과 JDBC 사이에서 동작 (DB와 연결하려면 JDBC 필요함)
2. JPA를 왜 사용해야 하는가?
- SQL 중심적인 개발에서 객체 중심으로 개발
- 생산성 : 자바 컬렉션에서 조회하듯이.
- 유지보수 : 기존에는 필드 변경시 모든 SQL 수정해야 했지만, JPA는 필드만 추가하면 된다.
- 위에 설명한 패러다임 불일치 해결
- 성능 최적화 기능
- 1차 캐시와 동일성 보장 : 같은 트랜잭션 안에서는 같은 엔티티 반환
- Isolation level이 Read Commit이어도 애플리케이션에서 Repeatable Read 보장
- 트랜잭션을 지원하는 쓰기 지연 (JDBC Batch SQL)
- 지연 로딩, 즉시 로딩 둘 다 지원
- 지연 로딩 : 객체가 실제 사용될 때 추가 로딩
- 즉시 로딩 : JOIN SQL로 한번에 연관된 객체까지 미리 조회
- 지연 로딩으로 전부 다 해놨다가, 성능 최적화를 위해 필요한 부분을 즉시 로딩 하는 방식으로 변환
- 1차 캐시와 동일성 보장 : 같은 트랜잭션 안에서는 같은 엔티티 반환
3. 앞으로 실습 설정
- DBMS : H2 Database(경량형 DBMS)
- mysql, postgresql 은 보통 실무에서 많이 쓰는 것,
- H2는 테스트용도로 자주 쓴다.
- Java : jdk 17
- Java build tool : Maven
- Gradle은 yml또는 properties를 사용하지만 Maven은 xml 파일을 바탕으로 env설정한다.
- 아래의 옵션 설정을 query 날렸을 때 쿼리내용, 포맷처리, 주석추가 를 보이기 위해 설정한 것.
<?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="jakarta.persistence.jdbc.driver" value="org.h2.Driver"/>
<property name="jakarta.persistence.jdbc.user" value="sa"/>
<property name="jakarta.persistence.jdbc.password" value=""/>
<property name="jakarta.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"/>
</properties>
</persistence-unit>
</persistence>
- resources / META-INF / persistence.xml에 위와 같이 설정을 추가
- main에서 Persistence 클래스의 EntityManagerFactory를 통해 Persistence Unit의 이름으로 Persistence 등록
- EntityManagerFactory의 createEntityManager 메서드를 통해 EntityManager를 생성해 JPA를 사용한다.
- 참고로 이후 EM, EMF를 close()
- Spring Boot 별로 맞는 Hibernate 버전이 있다. 이를 참고할 것. https://docs.spring.io/spring-boot/appendix/dependency-versions/properties.html
4. DB Dialect
JPA는 특정 데이터베이스에 종속 X
각각의 DB가 제공하는 SQL 문법과 함수는 조금씩 다르다.
SQL 표준을 지키지 않는 특정 DB만의 고유한 기능이라고 보면 되겠다.
- 가변 문자 : mysql은 VARCHAR, Oracle은 VARCHAR2
- 문자열을 자르는 함수 : SQL 표준은 SUBSTRING(), Oracle은 SUBSTR()
- 페이징 : MySQL은 LIMIT, Oracle은 ROWNUM
hibernate.dialect 속성에 지정 (40가지 이상의 DB 방언을 지원)
5. 주의 사항
Entity Manager Factory는 App내 하나만 생성해서 App 전체에서 공유
WAS가 내려갈 때 EMF는 닫아줘야 한다.
Entity Manager는 쓰레드간 공유X (사용하고 버려야 한다.)
JPA의 모든 데이터 변경은 transaction 안에서 실행되어야 한다.
6. JPQL (객체 지향 SQL)
Q. 나이가 18살 이상인 회원을 모두 검색하고 싶다면?
➡️ JPQL을 통해서 조건에 맞는 데이터를 가져올 수 있다. (SQL과 유사.)
List<Member> result = em.createQuery("select m from Member as m", Member.class)
.setMaxResults(3)
.getResultList();
JPA를 사용하면 Entity 객체를 중심으로 개발한다.
문제는 검색 쿼리인데, 검색을 할 때도 엔티티 객체 대상으로 검색하기 위한 방식
필요한 데이터만 DB에서 불러오려면 결국 검색 조건이 포함된 SQL이 필요하기 떄문에 사용.
'정보 > Database' 카테고리의 다른 글
연관 관계 Mapping (3) (0) | 2024.11.17 |
---|---|
연관 관계 Mapping (2) (1) | 2024.11.15 |
연관 관계 Mapping (1) (0) | 2024.11.15 |
Entity Mapping (3) | 2024.11.15 |
JPA Persistence Context 는 Git과 흡사하다 (0) | 2024.11.13 |