카테고리 없음

[JPA] JPA

JABHACK 2025. 1. 3. 08:50

JPA

📌 객체 지향 프로그래밍 언어인 Java와 관계형 데이터베이스 간의 패러다임 불일치 문제를 해결하여 데이터베이스 작업을 객체 지향적으로 수행할 수 있도록 지원한다.

  • 객체 지향적으로 설계하면 SQL코드가 점점 복잡해진다. JDBC로 외래키로 참조를 구현해본 경험이 있으니 뭔 말인지 잘 알것이다. 이러한 문제를 해결하기 위해 JPA가 등장했다.
  • Java 애플리케이션에서 객체를 관계형 데이터베이스와 매핑하여 데이터를 처리할 수 있도록 지원하는 ORM(Object-Relational Mapping) 표준이다.

Java의 ORM 기술 표준(인터페이스)

  • 대표적인 구현체로 Hibernate를 주로 사용한다.
  • 표준으로 만들어지면 더욱 명확하게 정의하고 사용할 수 있는 장점이 생긴다.

 


1. JPA의 주요 개념

  1. ORM(Object-Relational Mapping):
    • 객체지향 프로그래밍의 객체와 관계형 데이터베이스의 테이블 간 매핑을 제공.
    • 예: Java 클래스의 필드 ↔ 데이터베이스 테이블의 컬럼.
  2. Java EE 표준:
    • JPA는 Java EE 표준 사양으로, 특정 구현체(Hibernate, EclipseLink 등)에 독립적.
  3. 추상화 제공:
    • SQL 작성 없이 데이터베이스 작업 가능.
    • JPA는 JPQL(Java Persistence Query Language)을 통해 객체 중심의 쿼리 제공.

2. JPA 주요 구성 요소

  1. Entity:
    • 데이터베이스 테이블과 매핑되는 Java 클래스.
    • @Entity 어노테이션을 사용하여 매핑.
    @Entity
    public class User {
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Long id;
        private String name;
        private String email;
    
        // Getters and Setters
    }
    
  2. EntityManager:
    • JPA의 핵심 인터페이스로, 엔티티를 관리.
    • 데이터베이스의 CRUD 작업을 처리.
    • 주요 메서드:
      • persist(): 엔티티 저장.
      • find(): 엔티티 조회.
      • merge(): 엔티티 갱신.
      • remove(): 엔티티 삭제.
  3. Persistence Context:
    • 엔티티를 관리하는 메모리 공간.
    • 1차 캐시로 작동하여 같은 엔티티를 중복 조회할 때 데이터베이스를 재호출하지 않음.
  4. JPQL:
    • JPA에서 사용하는 객체지향 쿼리 언어.
    • SQL과 유사하지만 엔티티와 속성을 대상으로 동작.
    String jpql = "SELECT u FROM User u WHERE u.name = :name";
    List<User> users = entityManager.createQuery(jpql, User.class)
                                    .setParameter("name", "John")
                                    .getResultList();
    

3. JPA의 동작 방식

  1. 객체를 생성하고 저장:
    • EntityManager를 사용해 Java 객체를 데이터베이스에 저장.
    • SQL은 JPA가 자동 생성.
    EntityManager em = entityManagerFactory.createEntityManager();
    em.getTransaction().begin();
    
    User user = new User();
    user.setName("John");
    user.setEmail("john@example.com");
    
    em.persist(user); // INSERT SQL 생성 및 실행
    em.getTransaction().commit();
    
  2. 데이터 읽기:
    • EntityManager의 find() 메서드를 사용해 데이터를 조회.
    • SQL은 자동 생성.
    User user = em.find(User.class, 1L); // SELECT SQL 생성 및 실행
    
  3. 데이터 갱신:
    • 엔티티 객체의 속성을 변경하면 JPA가 자동으로 데이터베이스에 반영(Dirty Checking).
    em.getTransaction().begin();
    user.setEmail("newemail@example.com"); // UPDATE SQL 생성 및 실행
    em.getTransaction().commit();
    
  4. 데이터 삭제:
    • remove() 메서드를 호출해 엔티티 삭제.
    em.getTransaction().begin();
    em.remove(user); // DELETE SQL 생성 및 실행
    em.getTransaction().commit();
    

4. JPA와 Hibernate의 관계

  • JPA는 표준이고, Hibernate는 JPA의 구현체입니다.
**JPA (Java Persistence API)**는 Java에서 ORM(Object-Relational Mapping)을 위한 인터페이스와 규약을 정의한 표준입니다.
Hibernate는 JPA 표준을 구현한 ORM 프레임워크입니다.
  • JPA를 사용하면 코드가 구현체에 종속되지 않으므로, 필요에 따라 Hibernate, EclipseLink 등을 교체 가능.
  • Hibernate는 JPA 기능 외에도 고유한 추가 기능을 제공.

5. JPA의 장점

  1. 생산성 향상:
    • SQL 작성이 줄어들고, 객체 중심으로 데이터를 처리.
  2. 데이터베이스 독립성:
    • 애플리케이션 코드는 데이터베이스에 종속되지 않음.
  3. 자동 관리:
    • 엔티티 상태(생성, 수정, 삭제 등)를 JPA가 관리.
  4. JPQL 제공:
    • 객체 중심의 쿼리 언어로 개발자 친화적.
  5. 캐싱:
    • 1차 캐시를 통해 불필요한 데이터베이스 호출을 최소화.

6. JPA의 단점

  1. 학습 곡선:
    • JPA는 설정이 많고, 내부 동작 원리를 이해해야 효율적으로 사용할 수 있음.
  2. 복잡한 쿼리:
    • JPQL은 복잡한 SQL(특히 여러 테이블의 JOIN) 작성 시 한계가 있음.
    • 이 경우 Native SQL을 사용해야 함.
  3. 성능 최적화 필요:
    • N+1 문제, 캐싱 전략, 데이터베이스 스키마 설계 등을 제대로 관리하지 않으면 성능 문제가 발생.
  4. 추가 오버헤드:
    • JPA가 SQL을 생성하고 실행하므로, 직접 SQL 작성보다 약간의 오버헤드 발생.

7. Spring Data JPA

Spring Data JPA는 JPA를 기반으로 한 스프링 프레임워크의 데이터 접근 계층 라이브러리로, JPA를 더욱 쉽게 사용할 수 있게 도와줍니다.

특징

  • 기본 CRUD 메서드 자동 제공.
  • 메서드 이름 기반 쿼리 생성.
  • JPQL 및 Native SQL 지원.

예제: Repository 인터페이스 정의

public interface UserRepository extends JpaRepository<User, Long> {
    List<User> findByName(String name);
}

사용 예제

@Service
public class UserService {
    @Autowired
    private UserRepository userRepository;

    public List<User> getUsersByName(String name) {
        return userRepository.findByName(name);
    }
}

8. JPA와 다른 데이터 접근 방식 비교

항목 JPA MyBatis JDBC

주요 방식 ORM SQL 매퍼 기반 직접 SQL 작성
생산성 높음 중간 낮음
유지보수 상대적으로 쉬움 중간 어렵다
성능 설정에 따라 최적화 가능 효율적 (SQL 직접 작성 가능) 효율적
사용 사례 객체 중심 데이터 처리 복잡한 SQL 처리 단순한 데이터 처리

9. JPA를 사용할 때 주의사항

  1. N+1 문제:
    • 연관 관계에서 데이터가 예상보다 더 많이 로드될 수 있음.
    • 해결책: Fetch Join 또는 @BatchSize 사용.
  2. 캐싱 전략 관리:
    • 1차 캐시와 2차 캐시 사용 시 일관성을 유지해야 함.
  3. 데이터베이스 트랜잭션 관리:
    • JPA는 트랜잭션이 필요하므로 Spring과 함께 사용하는 경우 @Transactional로 트랜잭션 범위를 명시.
  4. 복잡한 비즈니스 로직:
    • JPA만으로 모든 문제를 해결할 수 없으므로, 복잡한 쿼리는 Native Query 활용.

 

ORM(Object-Relational Mapping)

  • 객체와 관계형 DB를 자동으로 Mapping하여 패러다임 불일치 문제를 해결한다.
  • JDBC API

 

ORM(Object-Relational Mapping)

 🐳 객체 지향 프로그래밍의 객체와 관계형 데이터베이스의 테이블을 자동으로 매핑해주는 기술

 

1. ORM의 주요 개념

  1. 객체-관계 불일치 해결:
    • 객체지향 언어에서는 데이터를 객체로 표현하지만, 관계형 데이터베이스는 데이터를 테이블로 저장.
    • ORM은 객체와 테이블 간의 매핑을 통해 이 불일치를 해결.
  2. 자동화된 데이터 처리:
    • SQL 쿼리 작성 없이 객체를 사용하여 데이터 저장, 조회, 수정, 삭제를 처리.
  3. 데이터베이스 독립성:
    • ORM을 사용하면 코드가 특정 데이터베이스에 종속되지 않음.

2. ORM의 주요 기능

  1. CRUD 작업 자동화:
    • Create, Read, Update, Delete 작업을 객체를 통해 처리.
    • SQL 대신 메서드를 호출하여 데이터 조작.
  2. 객체와 테이블 매핑:
    • 클래스 → 테이블, 필드 → 컬럼으로 매핑.
  3. 연관 관계 매핑:
    • 객체의 연관 관계(1:1, 1:N, N:M)를 데이터베이스 테이블의 외래 키 관계로 매핑.
  4. 캐싱 지원:
    • 1차 캐시(영속성 컨텍스트) 및 2차 캐시를 통해 데이터베이스 호출 최소화.
  5. 쿼리 생성:
    • JPQL이나 Query DSL 등을 통해 객체 기반의 쿼리 작성 가능.

3. ORM의 장점

  1. 생산성 증가:
    • SQL 쿼리를 작성하지 않아도 CRUD 작업을 수행 가능.
    • 데이터베이스 처리 로직의 코드 양을 크게 줄임.
  2. 유지보수성 향상:
    • 객체 중심의 코드 작성으로 가독성이 높아지고, 데이터베이스 변경 시 코드 변경이 최소화.
  3. 데이터베이스 독립성:
    • 코드가 특정 DBMS에 의존하지 않으므로 DB를 쉽게 교체 가능.
  4. 보안 강화:
    • SQL 인젝션 같은 보안 취약점을 예방하기 쉬움.
  5. 연관 관계 처리:
    • 객체 간의 관계를 직접 정의하고 활용 가능.

4. ORM의 단점

  1. 학습 곡선:
    • ORM 도구의 설정 및 사용법을 이해하는 데 시간이 필요.
  2. 성능 문제:
    • ORM이 자동 생성한 쿼리가 비효율적일 수 있음.
    • 복잡한 쿼리는 직접 작성해야 할 수도 있음(Native Query 사용).
  3. 디버깅 어려움:
    • ORM이 생성한 SQL을 디버깅하거나 최적화하기 어렵다.
  4. 추상화 한계:
    • 데이터베이스 고유 기능(예: 저장 프로시저, 특정 SQL 구문) 사용 시 어려움.

5. ORM 동작 방식

1) 매핑 설정

객체를 데이터베이스 테이블에 매핑.

  • 클래스는 테이블에 매핑.
  • 필드는 테이블의 컬럼에 매핑.

Java JPA 예제:

@Entity
@Table(name = "users")
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(nullable = false)
    private String name;

    @Column(unique = true, nullable = false)
    private String email;

    // Getters and Setters
}

 

2) 데이터 저장

객체를 데이터베이스에 저장하면, ORM이 INSERT 쿼리를 생성하고 실행.

User user = new User();
user.setName("John Doe");
user.setEmail("john@example.com");

entityManager.persist(user); // INSERT SQL 실행

3) 데이터 조회

객체를 조회하면 ORM이 자동으로 SELECT 쿼리를 생성.

User user = entityManager.find(User.class, 1L); // SELECT SQL 실행

 

 

6. JPA와 ORM의 관계

  • JPA는 Java에서 ORM 표준을 정의한 API.
  • Hibernate, EclipseLink 같은 구현체는 JPA의 표준을 따르며, 이를 기반으로 ORM 기능 제공.

7. ORM 사용 시 주의점

  1. N+1 문제:
    • 연관된 데이터를 가져올 때 추가적인 쿼리가 반복 실행될 수 있음.
    • 해결책: Fetch Join, @BatchSize 사용.
  2. 복잡한 쿼리:
    • 복잡한 JOIN 쿼리나 데이터베이스 고유 기능 사용 시 Native Query 작성 필요.
  3. 캐싱 전략 관리:
    • 1차 캐시와 2차 캐시 사용을 적절히 조정해야 성능을 최적화.
  4. 스키마 설계:
    • ORM은 데이터베이스 설계를 자동화하지 않으므로, 스키마 설계는 여전히 중요.

8. ORM이 적용된 데이터 처리 흐름

  1. 애플리케이션 개발:
    • 개발자는 객체(Entity) 중심으로 코드를 작성.
  2. ORM 매핑:
    • ORM이 객체와 테이블 간의 매핑을 수행.
  3. 쿼리 생성 및 실행:
    • CRUD 작업 시 ORM이 SQL을 생성하여 데이터베이스와 통신.
  4. 결과 매핑:
    • SQL 실행 결과를 객체로 변환하여 반환.

 

 

 

 

Java EE 표준

 🐳 Java를 사용하여 대규모 엔터프라이즈 애플리케이션을 개발하기 위한 표준 플랫폼입니다.

 

1. Java EE의 주요 개념

  1. 표준화된 사양:
    • 엔터프라이즈 애플리케이션 개발을 위한 API와 스펙이 표준화되어 있어 다양한 구현체에서 동일하게 작동.
  2. 컨테이너 기반 실행 환경:
    • Java EE 애플리케이션은 애플리케이션 서버(Java EE 컨테이너)에서 실행되며, 컨테이너가 리소스 관리, 보안, 트랜잭션 등을 처리.
  3. 엔터프라이즈 개발 도구:
    • 데이터베이스 액세스, 메시징, 웹 서비스, 의존성 주입 등 대규모 애플리케이션에 필요한 기능 제공.

2. Java EE의 주요 구성 요소

1) Web Tier

  • Servlet:
    • HTTP 요청/응답을 처리하는 자바 기반 웹 컴포넌트.
  • JSP (Java Server Pages):
    • HTML과 Java 코드를 결합하여 동적인 웹 콘텐츠 생성.
  • JSF (Java Server Faces):
    • MVC 패턴을 기반으로 한 컴포넌트 기반 UI 프레임워크.

2) Business Tier

  • EJB (Enterprise JavaBeans):
    • 트랜잭션, 보안, 동시성 관리 등을 포함한 비즈니스 로직 실행.
  • CDI (Contexts and Dependency Injection):
    • 의존성 주입(Dependency Injection)을 제공하여 객체 간의 결합도 감소.

3) Persistence Tier

  • JPA (Java Persistence API):
    • ORM(Object Relational Mapping) 표준으로, 데이터베이스와 객체 간의 매핑을 제공.

4) Integration Tier

  • JMS (Java Messaging Service):
    • 메시징 시스템과 통합을 지원.
  • JAX-RS (Java API for RESTful Web Services):
    • RESTful 웹 서비스 개발을 위한 API.
  • JAX-WS (Java API for XML Web Services):
    • SOAP 기반 웹 서비스 개발을 지원.

5) Other APIs

  • JTA (Java Transaction API):
    • 분산 트랜잭션 관리.
  • JavaMail:
    • 이메일 송수신 기능 제공.
  • Batch API:
    • 대량 데이터 처리(batch processing) 지원.

3. Java EE의 특징

  1. 표준 기반:
    • 모든 Java EE 애플리케이션은 표준화된 API를 사용하므로 다양한 애플리케이션 서버에서 동작.
  2. 확장성:
    • 모듈 기반 설계를 통해 애플리케이션을 확장하기 쉽고, 대규모 애플리케이션 개발에 적합.
  3. 컨테이너 관리:
    • Java EE 컨테이너가 보안, 트랜잭션, 리소스 관리, 의존성 주입 등을 자동으로 처리.
  4. 플랫폼 독립성:
    • Java 기반으로 설계되었기 때문에 플랫폼에 독립적.
  5. 다양한 구현체 지원:
    • 다양한 Java EE 구현체(Hibernate, WildFly, GlassFish, Apache TomEE 등)에서 실행 가능.

4. Java EE의 주요 애플리케이션 서버

Java EE 사양은 여러 애플리케이션 서버에서 구현됩니다. 대표적인 서버는 다음과 같습니다:

서버 특징
GlassFish Oracle가 Java EE의 참조 구현체로 제공한 서버. 현재는 Eclipse 재단에서 관리.
WildFly JBoss의 오픈소스 애플리케이션 서버.
Apache TomEE Tomcat 기반 경량 Java EE 서버.
WebLogic Oracle에서 제공하는 상용 애플리케이션 서버.
WebSphere IBM의 상용 엔터프라이즈 애플리케이션 서버.

5. Jakarta EE와의 관계

  • 2017년, Oracle이 Java EE의 관리를 Eclipse 재단에 넘기면서 이름이 Jakarta EE로 변경됨.
  • 최신 표준은 Jakarta EE이며, 기존 Java EE의 발전된 버전.

6. Java EE의 주요 사용 사례

  1. 엔터프라이즈 애플리케이션:
    • 대규모 비즈니스 로직을 처리하는 시스템 개발.
    • 예: 금융, 통신, 물류 시스템.
  2. 웹 애플리케이션 개발:
    • JSP, Servlet, JSF 등을 사용하여 웹 애플리케이션 구현.
  3. 분산 시스템:
    • EJB, JMS를 활용하여 여러 시스템 간의 통합.
  4. RESTful API 개발:
    • JAX-RS를 사용하여 RESTful 웹 서비스를 개발.
  5. 데이터 처리:
    • JPA와 JDBC를 통해 데이터베이스와 상호작용.

7. Java EE의 장단점

장점

  1. 표준화:
    • 다양한 구현체에서 동일한 사양을 따름.
  2. 풍부한 기능:
    • 엔터프라이즈 애플리케이션 개발에 필요한 대부분의 기능 포함.
  3. 확장성과 유연성:
    • 대규모 시스템 설계 및 확장에 적합.
  4. 컨테이너 관리:
    • 트랜잭션, 보안 등 복잡한 작업을 컨테이너가 자동 처리.

단점

  1. 복잡성:
    • 학습 곡선이 높으며, 초기 설정과 구조 설계가 복잡.
  2. 무거운 사양:
    • Java EE의 모든 기능을 사용하지 않더라도 큰 오버헤드가 있을 수 있음.
  3. 의존성:
    • 애플리케이션 서버의 성능 및 설정에 영향을 받음.

8. Java EE의 기본 동작 흐름

  1. 클라이언트 요청:
    • HTTP 요청 또는 메시지 큐를 통해 서버로 전달.
  2. Web Tier 처리:
    • Servlet, JSP 또는 JSF에서 요청을 처리.
  3. Business Tier 처리:
    • EJB 또는 POJO에서 비즈니스 로직 실행.
  4. Database와 상호작용:
    • JPA 또는 JDBC를 통해 데이터베이스에 접근.
  5. 응답 생성:
    • 처리 결과를 클라이언트로 반환.

 

 

생산성

// 저장
jpa.persist(tutor);
// 조회
Tutor tutor = jpa.find(Tutor.class, tutorId);
// 수정
tutor.setName("수정할 이름");
// 삭제
jpa.remove(tutor);
  • persist란 영구히 저장한다는 뜻
  • 마치 컬렉션에 저장한듯 객체가 저장되어 조회가 간편하다.
  • 수정하고자 할 때 꺼낸 객체에 setName() 하면된다.

 

유지보수성

// 기존
public class Tutor {
		private String id;
		private String name;
}
 
// 필드 수정
public class Tutor {
		private String id;
		private String name;
		private Integer age;
}
  • 객체 필드가 수정 되어도 SQL은 JPA가 알아서 처리한다.

 

패러다임 불일치 문제 해결

 

상속

 

연관관계

tutor.setCompany(company);
jpa.persist(company);
  • Collection처럼 사용할 수 있다.

 

객체 그래프 탐색

Tutor tutor = jpa.find(Tutor.class, tutorId);
Company company = tutor.getCompany();
  • JPA를 사용하면 신뢰할 수 있는 엔티티, 계층이 된다.
    • JOIN or SQL Query 두번 실행은 JPA로 편하게 할 수 있다.

 

객체 비교

Tutor tutor1 = jpa.find(Tutor.class, tutorId);
Tutor tutor2 = jpa.find(Tutor.class, tutorId);

tutor1 == tutor2; // true
  • 단, 전제조건으로 동일한 트랜잭션 필수

 

 

성능

  • 1차 캐시
    • SQL Query 한번만 실행
Tutor tutor1 = jpa.find(Tutor.class, tutorId); // 실행 결과 1차 캐시에 저장
Tutor tutor2 = jpa.find(Tutor.class, tutorId); // 캐시에서 조회

tutor1 == tutor2; // true
  • 쓰기 지연
    • ORM과 같은 중간 기술이 있으면 한번에 모아서 요청을 보내는것이 가능하다.
    • 네트워크 통신이 한번만 발생하여 비용이 감소된다.
// 트랜잭션 시작
transaction.begin();

jpa.persist(company);
jpa.persist(tutor1);
jpa.persist(tutor2);

// 트랜잭션 제출, JDBC BATCH SQL
transaction.commit();
  • 지연 로딩, 즉시 로딩
    •  
// 지연 로딩
Tutor tutor = tutorRepository.find(tutorId); // SELECT * FROM tutor
Company company = tutor.getCompany();
String companyName = company.getName(); // SELECT * FROM company

// 즉시 로딩
// SELECT t.*, c.* FROM tutor t JOIN Company c ON
Tutor tutor = tutorRepository.find(tutorId);

Company company = tutor.getCompany();
String companyName = company.getName();
  • 지연로딩
    • 필요할 때만 조회하기 때문에 통신 비용 감소
  • 즉시로딩
    • 한번만 조회하기 때문에 네트워크 통신 비용 감소

 

hibernate.dialect

📌 Hibernate가 사용하는 데이터베이스 방언(dialect)을 지정하는 설정으로 데이터베이스와 Hibernate가 상호작용할 때 특정 데이터베이스에 맞게 SQL 구문을 자동으로 조정하는 역할을 수행한다.

  • 데이터베이스 방언(Dialect) = 서로 다른 데이터베이스 시스템의 SQL 문법과 기능 차이를 처리하기 위해 제공

  • 방언 : SQL 표준을 지키지 않는 특정 데이터베이스 만의 고유한 기능

ex) 페이징

  • MySQL : LIMIT
  • Oracle : ROWNUM
  • JPA는 특정 데이터베이스에 종속되지 않는다.
    • MySQL → Oracle 마음대로 변경이 가능하다.
  • 실무에서 사용되는 DB의 Dialect는 대부분 이미 존재한다.