hyeonga_code

PreProject_03_ORM(Object-Relational Mapping) 을 위한 Entity Class 본문

Project_HYEONGARL

PreProject_03_ORM(Object-Relational Mapping) 을 위한 Entity Class

hyeonga 2024. 5. 12. 05:59
반응형

 


영속성 Persistence
프로그램이 종료되어도 데이터가 사라지지 않고 저장되는 개념

 

 

SQL Mapper

Object와 SQL의 필드를 매핑하여 데이터를 객체화합니다.

객체와 테이블 간의 관계를 매핑하는 것이 아니라 SQL 문을 직접 작성하고 쿼리 수행 결과를 어떠한 객체에 매핑할 지 바인딩하는 방법입니다.

DBMS에 종속적인 문제점을 가질 수 있습니다.

JDBC Template, MyBatis가 포함됩니다.

 

ORM Object-Relational Mapping

객체 지향 프로그래밍 언어와 관계형 데이터베이스 간의 호환성을 높이기 위해 사용되는 프로그래밍 기법입니다.

데이터베이스 테이블을 객체로 매핑하여 데이터베이스 작업을 직관적이고 객체 지향적으로 처리할 수 있습니다.

 

객체와 데이터베이스의 테이블을 자동으로 매핑하여 RDB 테이블을 객체 지향적으로 사용할 수 있습니다.

애플리케이션 객체를 RDB 테이블에 자동으로 영속화해주는 것으로 볼 수 있습니다.

 


객체 지향 프로그래밍은 클래스를 사용
관계형 데이터베이스는 테이블을 사용

객체 모델과 관계형 모델 간에는 불일치가 존재하는데 ORM을 통해 객체 간의 관계를 바탕으로 SQL을 자동으로 생성하여 불일치를 해결할 수 있습니다.

 

장점

1. 직관적이고 가독성이 좋다

Query와 같이 필요한 선언문, 할당 등의 부수적인 코드가 줄고 각종 객체에 대한 코드를 별도로 작성하여 코드의 가독성이 높아진다.

 

2. 객체 지향적 접근으로 생산성이 증가한다.

SQL 문이 아닌 클래스의 메소드를 통해 데이터베이스를 조작하여 개발자가 객체 모델만 이용하여 프로그래밍을 하는 데 집중할 수 있습니다.

SQL의 절차적이고 순차적인 접근이 아닌 객체지향적인 접근으로 인해 생산성을 높일 수 있습니다.

 

3. 재사용 및 유지보수의 용이성 증가

ORM은 독립적으로 작성되어 있고, 해당 객체를 재활용할 수 있습니다.

매핑 정보가 명확하여 ERD를 보는 것에 대한 의존도를 낮출 수 있습니다.

 

4. DBMS에 대한 종속성 감소

객체 간의 관계를 바탕으로 SQL을 자동으로 생성하므로 RDBMS의 데이터 구조와 Java의 객체 지향 모델 사이의 간격을 좁힐 수 있습니다.

ORM은 특정 DB에 종속적이지 않으므로 DBMS를 교체하는 큰 작업에도 비교적 적은 리스크와 시간이 소요됩니다.

 

단점

1. 잘못 구현된 경우 속도 저하가 발생할 수 있습니다.

2. 복잡한 Query의 경우 QueryDSL 등을 사용하여 직접 처리해야 합니다.

 

 

 

 

MyBatis vs Hibernate

현재 한국은 SI 혹은 금융쪽으로 비즈니스가 매우 복잡하고 안정성과 속도를 중요시하여 MyBatis를 사용하는 것이 나을 수 있습니다. 그러나 MyBatis는 쿼리를 직접 작성해야 하므로 Hibernate에 능숙해지면 생산성을 높일 수 있습니다.

JPA를 사용하며 통계나 동적 쿼리 같은 복잡한 쿼리를 처리하는 것이 어려워 QueryDSL을 함께 이용합니다.

 

MyBatis는 오픈 소스 라이브러리입니다.

JPA는 Java 객체와 테이블을 매핑시켜야 하므로 매핑 정보를 Java 클래스에 작성해야 합니다.

 

 

JPA 배경

자바 기반의 애플리케이션 개발에서 객체-관계 매핑을 처리하는 과정에서 발생하는 문제를 해결하고자 함에 있습니다.

기존에는 JDBC를 사용했으나 직접 SQL 문을 작성하여 반복적인 코드가 발생하고 객체에서 필드를 수정하는 경우 SQL도 수정이 필요하여 패러다임의 불일치가 발생합니다.

 

 

JPA의 장점

1. 엔티티에 맞는 테이블 생성 + DB 생성이 편리하다

설정에 따라 매핑된 객체를 바탕으로 테이블을 자동으로 생성합니다.

자동 생성되는 이름이 가독성이 좋지는 않으나 모든 DDL을 작성하는 것보다 편리합니다.

2. 객체 지향 중심의 개발

3. 테스트 작성이 용이하다

Repository 계층은 데이터베이스와 데이터를 주고 받는 계층으로 단위 테스트로 작성하는 것보다 DB와 연결하여 실제 쿼리를 처리하는 통합 테스트를 진행하는 것이 좋습니다.

4. CRUD의 자동화

persist() : 저장

find() : 조회

setName() : 수정

remove() : 삭제

5. 복잡한 쿼리의 경우 QueryDSL을 사용하여 처리

 

JPA 작동 방식

애플리케이션과 JDBC 사이에서 동작합니다.

DAO 클래스를 통해 find(id)를 호출하면 JPA는 SELECT SQL을 생성합니다.

JDBC API를 사용하여 생성된 SELECT SQL을 DB로 보냅니다.

DB에서 반환된 정보를 ResultSet 매핑을 통해 Entity 객체로 변환합니다.

이 과정에서 패러다임 불일치 문제를 해결합니다.

 

JPA Java Persistence API

Java에서 ORM 기술 표준으로 사용하는 인터페이스의 모음입니다.

Java 애플리케이션에서 관계형 데이터베이스를 사용하는 방식을 정의한 인터페이스입니다.

Hibernate, Open JPA 등이 구현하고 있습니다.

대부분 Hibernate 구현체를 사용합니다.

 

왜 JPA?

1. JPA는 반복적인 CRUD SQL을 처리합니다.

매핑된 관계를 이용하여 SQL을 생성하고 실행합니다.

MyBatis를 사용하는 경우 간단한 쿼리도 모두 작성해야 하지만 JPA를 이용하는 경우 생산성을 높일 수 있습니다.

 

2. 객체 중심으로 개발할 수 있습니다.

SQL이 아닌 객체를 중심으로 개발할 수 있습니다.

테이블에 매핑되는 클래스를 좀 더 객체 지향적으로 개발할 수 있습니다.

 

dependencies {
	implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
}

 

 

Java 의 Hibernate

JPA(Java Persistence API) 표준을 따릅니다.

 

Java에서 사용하는 Hibernate 를 위한 Entity Class

Entity Class

데이터베이스 테이블에 저장되는 데이터를 나타내는 클래스입니다.

 

@Entity

클래스가 데이터베이스 테이블에 매핑되는 엔티티임을 지정합니다.

기본 값으로 클래스의 카멜케이스 이름을 언더스코어 네이밍으로 테이블 이름을 매칭합니다.

 

@Id

엔티티의 기본 키 필드임을 지정합니다. (PK)

 

@GeneratedValue

기본키의 생성 전략을 지정합니다.

IDENTITY 전략은 데이터베이스가 자동으로 ID를 생성하도록 합니다.

Spring Boot 2.0 부터 auto_increment를 위해 GenerationType.IDENTITY 옵션을 추가해야 합니다.

 

@Column

특정 필드를 데이터베이스 컬럼과 매핑합니다. (컬럼 이름, 널 허용 여부, 길이 등을 지정할 수 있습니다.)

기본 값 이외에 변경이 필요한 옵션이 존재하는 경우 사용합니다.

 

@Transient

데이터베이스에 저장되지 않는 변수로 DTO로서의 역할을 합니다.

 

@Builder

해당 클래스의 빌드 패턴 클래스를 생성합니다.

생성자 상단에 선언하는 경우 생성자에 포함된 필드만 빌더에 포함됩니다.

 

 

@Entity
public class Sample {
	
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    @Column(name = "name", nullable = false, length=50)
    private String name;

    @Transient
    private String memo;
}

 

 

Repository

JPA 에서 DBLayer 접근자를 의미합니다.

인터페이스를 생성하고 JpaRepository<'Entity 클래스', 'PK 타입'> 을 상속하면 기본적인 CRUD 메소드가 자동으로 생성되며 @Repository를 추가할 필요가 없습니다.

public interface SampleRepository extends JpaRepository<Sample, Long> {

}

 

 

주의사항

1. Entity의 PK는 Long 타입의 Auto_increment 를 사용하도록 하는 것이 좋습니다.

주민등록번호와 같은 비즈니스 상의 유니크 키나 복합키 등은 유니크 키로 별도로 추가하는 것이 좋습니다.

1) FK를 맺을 때 다른 테이블에서 복합키 전부를 가지고 있거나 중간 테이블을 하나 더 만들어야 하는 상황이 발생할 수 있습니다.

2) 인덱스에 좋지 않은 영향을 미칠 수 있습니다.

3) 유니크한 조건 변경시 PK 전체 수정이 필요할 가능성이 있습니다.

 

2. Entitty 클래스에서는 Setter 대신 @Builder 를 통해 제공되는 빌더 클래스를 사용합니다.

getter/setter를 무작정 생성하는 경우 해당 클래스의 인스턴스 값이 어디서 변경되는지 코드상으로 명확하게 구분할 수 없어 기능 변경 시 불편합니다.

 

생성자 : 생성 시점에 값을 실어 코드 실행 전까지 값을 실을 필드를 명확하제 지정하는 것이 불가합니다.

빌더 클래스 : 생성자와 동일한 역할을 하지만 코드 실행 전에 값을 실을 필드를 명확하게 인지할 수 있습니다.

기본적으로 생성자를 통해 값을 DB에 삽입하고 값 변경은 해당 이벤트에 맞는 public 메소드를 호출하여 처리합니다.

생성자는 인자로 잘못된 값을 전달하는 등의 문제 발생의 여지가 존재하므로 빌더 클래스를 사용하는 것을 권합니다.

 

3. Entity 클래스와 기본 Entity Repository는 밀접한 관계를 맺고 있으므로 함께 관리합니다.

 

 

반응형

'Project_HYEONGARL' 카테고리의 다른 글

PreProject_06_Controller  (0) 2024.05.13
PreProject_05_ResponseEntity<>  (0) 2024.05.13
PreProject_04_Spring Web Layer  (0) 2024.05.13
PreProject_02_REST  (0) 2024.05.11
PreProject_01_MVC 모델 짚고 넘어가기  (0) 2024.05.11