2.3 라이브러리와 프로젝트 구조
- 메이븐
- 라이브러리를 관리하고 빌드함
- 라이브러리 관리 기능 = 자바 애플리케이션을 개발하려면 jar 파일로 된 여러 라이브러리가 필요하다.
- 과거에는 이런 라이브러리를 직접 내려받아 사용했다.
- 메이븐은 사용할 라이브러리 이름과 버전만 명시하면 라이브러리를 자동으로 내려받고 관리
- 빌드 기능 = 애플리케이션을 빌드하는 표준화된 방법을 제공
- 라이브러리 관리 기능 = 자바 애플리케이션을 개발하려면 jar 파일로 된 여러 라이브러리가 필요하다.
- gradle
- 기본 메이븐의 경우 XML로 라이브러리를 정의하고 활용하도록 되어 있으나, Gradle의 경우 별도의 빌드스크립트를 통하여 사용할 어플리케이션 버전, 라이브러리등의 항목을 설정 할 수 있다.
- 라이브러리를 관리하고 빌드함
- JPA 구현체로 하이버네이트를 사용하기 위한 핵심 라이브러리
-
- hibernate-core : 하이버네이트 라이브러리
-
- hibernate-entitymanager : 하이버네이트가 JPA 구현체로 동작하도록 JPA 표준을 구현한 라이브러리
-
- hibernate-jpa2.1-api : JPA 2.1 표준 API를 모아둔 라이브러리
-
2.4 객체 매핑 시작
package com.jiyun.Jpasession.domain;
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
@NoArgsConstructor //해당 클래스에 기본 생성자를 만들줌 -> @Entity가 그 기능을 하지만 붙이는 이유는 기본생성자를 추가하되, 접근제한을 걸어서 안전성도 높이는 것이다.
@Table(name = "member")
@Entity
public class Member {
@Id
@Column(name = "ID") //PK가 된다.
private String id;
@Column(name = "NAME")
private String username;
//매핑 정보가 없는 필드
private Integer age;
}
@Entity
- 이 클래스를 테이블과 매핑한다고 JPA에게 알려준다.
- 이렇게 @Entity가 사용된 클래스 = 엔티티 클래스
@Table
- 엔티티 클래스에 매핑할 테이블 정보를 알려줌
- 생략 시 엔티티 이름을 테이블명으로 매핑한다.
@Id
- 엔티티 클래스의 필드를 테이블의 기본키에 매핑한다.
- 식별자 필드
@Column
- 필드를 컬럼에 매핑한다.
- 매핑 정보가 없는 필드
- 칼럼명으로 매핑한다.
2.5 persistence.xml
- 책에서는 h2를 이용하지만 필자는 mysql로 해보기로 했다.
- JPA 설정 파일은 /META-INF/persistence.xml 위치 persistence-unit name으로 이름 지정 javax.persistence로 시작: JPA 표준 속성 hibernate로 시작: 하이버네이트 전용 속성
hellojpa.Member
- JPA 설정은 영속성 유닛이라는 것부터 시작하는데 일반적으로 연결할 데이터베이스 당 하나의 영속성 유닛을 등록한다. → persistence-unit name으로 이름
- JPA 표준 속성
- javax.persistence로 시작
- 특정 구현체에 종속되지 않는다. → hibernate로 시작하는 것은 하이버네이트 전용 속성이므로 하이버네이트에서만 사용 가능
- 하이버네이트 전용 속성
- hibernate로 시작
- 가장 중요하면 속성 = hibernate.dialect
2.5.1 데이터베이스 방언
- JPA는 특정 데이터베이스에 종속적이지 않은 기술 → 다른 데이터베이스로 손쉽게 교체 가능
- 하지만 데이터베이스마다 차이점이 있음 ⇒ 특정 데이터베이스만의 고유한 기능을 JPA에서는 “방언”이라고 한다.
- 데이터 타입
- 다른 함수명
- 페이징 처리
- 하이버네이트를 포함하는 대부분의 JPA 구현체들은 이런 문제(특정 데이터베이스에 종속되어 교체할 때 어려움을 겪음)를 해결하려고 다양한 데이터베이스 방언 클래스를 제공한다.
- ⇒ 데이터베이스가 변경되어도 어플리케이션의 코드를 변경할 필요는 없다. (방언만 변경하면 된다)
2.6 애플리케이션 개발
package com.jiyun.Jpasession;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
@SpringBootApplication
public class JpasessionApplication {
public static void main(String[] args) {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");//엔티티 메니저 팩토리 생성
EntityManager em = emf.createEntityManager(); //엔티티 매니저 생성
EntityTransaction tx = em.getTransaction(); //트랜잭션 획득
try{
tx.begin();//트랜잭션 시작
logic(em);//비즈니스 로직 시작
tx.commit(); //트랜잭션 커밋
}catch (Exception e){
tx.rollback(); //트랜잭션 롤백
} finally {
em.close(); //엔티티 매니저 종료
}
emf.close(); //엔티티 매니저 팩토리 종료
private static void logic(EntityManager em){}
}
}
크게 3부분으로 나뉨
- 엔티티 매니저 생성
- 트랜잭션 관리
- 비즈니스 로직
2.6.1 엔티티 매니저 설정
- 엔티티 매니저 팩토리 생성이때, Persistence 클래스를 사용하는데 이 클래스는 엔티티 메니저 팩토리를 생성해서 JPA를 사용할 수 있게 준비한다.
- persistence.xml에서 이름이 hello인 영속성 유닛을 찾아서 엔티티 매니저 팩토리를 생성한다.
- 엔티티 메니저 팩토리는 애플리케이션 전체에서 딱 한 번만 생성하고 공유해서 사용
- persistence.xml의 설정 정보를 읽어서 JPA를 동작시키기 위한 기반 객체를 만들고 JPA 구현체에 따라서는 데이터베이스 커넥션 풀도 생성하므로 엔티티 매니저 팩토리를 생성하는 비용은 아주 크다,
- 엔티티 메니저 팩토리는 애플리케이션 전체에서 딱 한 번만 생성하고 공유해서 사용
- persistence.xml에서 이름이 hello인 영속성 유닛을 찾아서 엔티티 매니저 팩토리를 생성한다.
- EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
- JPA를 시작하려면 우선 persistence.xml의 설정 정보를 사용해서 엔티티 매니저 팩토리를 생성해야 한다.
- 엔티티 매니저 생성
- EntityManager em = emf.createEntityManager()
- *참고 = 엔티티 매니저는 데이터베이스 커넥션과 밀접한 관계가 있으므로 스레드 간에 공유하거나 재사용하면 안 된다.
- 엔티티 매니저는 내부에 데이터 커넥션을 유지하면서 데이터베이스와 통신한다.
- JPA의 기능 대부분은 이 엔티티 매니저가 제공한다.
- 종료
- 사용이 끝난 엔티티 매니저는 반드시 종료를 해야 한다.
- em.close();
- 애플리케이션을 종료할 때 엔티티 매니저 팩토리도 다음처럼 종료해야 한다.
- emf.close()
2.6.2 트랜잭션 관리
- JPA를 사용하면 항상 트랜잭션 안에서 데이터를 변경해야 한다.
- 트랜잭션없이 데이터를 변경하면 예외가 발생
- 트랜잭션을 시작하려면 엔티티 매니저에서 트랜잭션 API를 받아와야 한다.
- 정상 동작하면 커밋을, 예외가 발생하면 트랜잭션 롤백을 한다.
2.6.3 비즈니스 로직
- 등록, 수정, 삭제, 조회 작업이 엔티티 매니저를 통해서 수행된다.
// 저장
// Member member = new Member();
// member.setId(1L); // Long 값이라 L 붙인 것.
// member.setName("HelloA");
// em.persist(member); // member 저장
// 조회
// Member findMember = em.find(Member.class, 1L);
// System.out.println("findMember.id = " + findMember.getId());
// System.out.println("findMember.name = " + findMember.getName());
// 삭제
// Member findMember = em.find(Member.class, 1L);
// em.remove(findMember)
// 수정
// Member findMember = em.find(Member.class, 1L);
// findMember.setName("HelloJPA");
// 저장 안하고 그냥 끝내도 된다. 마치 자바 컬렉션을 다루듯이 사용하면 된다.
2.6.4 JPQL
- JPA를 사용하면 엔티티 객체를 중심으로 개발한다. 문제는 검색 쿼리
- 검색을 할 때도 테이블이 아닌 엔티티 객체를 대상으로 검색한다.
- 모든 DB 데이터를 객체로 변환해서 검색하는 것은 불가능 애플리케이션이 필요한 데이터만 DB에서 불러오려면 결국 검색 조건이 포함된 SQL이 필요 = JPQL
- JPA는 SQL을 추상화한 JPQL이라는 객체 지향 쿼리 언어 제공 = JPQL
- SQL과 문법 유사, SELECT, FROM, WHERE, GROUP BY, HAVING, JOIN 지원
- JPQL은 엔티티 객체를 대상으로 쿼리
- SQL은 데이터베이스 테이블을 대상으로 쿼리
- 테이블이 아닌 객체를 대상으로 검색하는 객체 지향 쿼리
- SQL을 추상화해서 특정 데이터베이스 SQL에 의존X 설정 파일에 적은 방언과 합쳐져서 특정 DB에 맞는 SQL을 실행시켜준다.
- JPQL을 한마디로 정의하면 객체 지향 SQL
'WEB > Spring' 카테고리의 다른 글
[JPA] 7장 복합 키와 식별 관계 매핑 (0) | 2023.08.08 |
---|---|
[Spring Security] 스프링 시큐리티란? (0) | 2023.03.08 |
[JPA] JPA와 JPA의 필요성 (0) | 2023.02.26 |
빈 생명주기 콜백 (1) | 2022.09.11 |
같은 타입인 여러 개의 빈들을 조회하고 싶을 때 (1) | 2022.09.10 |