해당 게시글은 스프링부트 핵심 가이드 교재를 공부하며 작성한 글입니다.
06. 데이터베이스 연동
ORM
- Object Relational Mapping의 약자
- 객체 관계 매핑
- 객체지향 언어에서 의미하는 객체와 RDB(Relational Database)의 테이블을 자동으로 매핑하는 방법
- 쿼리문 작성이 아닌 코드(메서드)로 데이터를 조작할 수 있다.
ORM의 장점
- ORM을 사용하면 데이터베이스 쿼리를 객체지향적으로 조작할 수 있다.
- 쿼리문을 작성하는 양이 현저히 줄어 개발 비용이 줄어든다.
- 객체지향적으로 데이터베이스에 접근할 수 있어 코드의 가독성을 높인다.
- 재사용 및 유지보수가 편리하다.
- ORM을 통해 매핑된 객체는 모두 독립적으로 작성되어 있어 재사용이 용이하다.
- 객체들은 각 클래스로 나뉘어 있어 유지보수가 수월하다.
- 데이터베이스에 대한 종속성이 줄어든다.
- ORM을 통해 자동 생성된 SQL문은 객체를 기반으로 데이터베이스 테이블을 관리하기 때문에 데이터베이스에 종속적이지 않다.
- 데이터베이스를 교체하는 상황에서도 비교적 적은 리스크를 부담한다.
ORM의 단점
- ORM만으로 온전한 서비스를 구현하기에는 한계가 있다.
- 복잡한 서비스의 경우 직접 쿼리를 구현하지 않고 코드로 구현하기 어렵다.
- 복잡한 쿼리를 정확한 설계 없이 ORM 만으로 구성하게 되면 속도 저하 등의 성능 문제가 발생할 수 있다.
- 애플리케이션의 객체 관점과 데이터베이스의 관계 관점의 불일치가 발생한다.
- 세분성(Granularity) : ORM의 자동 설계 방법에 따라 데이터베이스에 있는 테이블의 수와 애플리케이션의 엔티티(Entity) 클래스의 수가 다른 경우 생긴다.(클래스가 테이블의 수보다 많아질 수 있다.)
- 상속성(Inheritance) : RDBMS에는 상속이란 개념이 없다.
- 식별성(Identity) : RDBMS는 기본 키(primary key)로 동일성을 정의한다. 하지만 자바는 두 객체의 값이 같아도 다르다고 판단할 수 있다. 식별과 동일성의 문제다.
- 연관성(Associations) : 객체지향 언어는 객체를 참조함으로써 연관성을 나타내지만 RDBMS에서는 외래키(foreign key)를 삽입함으로써 연관성을 표현한다. 또한 객체지향 언어에서 객체를 참조할 때는 방향성이 존재하지만 RDBMS에서 외래키를 삽입하는 것은 양방향의 관계를 가지기 때문에 방향성이 없다.
- 탐색(Navigation) : 자바와 RDBMS는 어떤 값(객체)에 접근하는 방식이 다르다. 자바에서는 특정 값에 접근하기 위해 객체 참조 같은 연결 수단을 활용한다. 이 방식은 객체를 연결하고 또 연결해서 접근하는 그래프 형태의 접근 방식이다. 반면 RDBMS에서는 쿼리를 최소화하고 조인(JOIN)을 통해 여러 테이블을 로드하고 값을 추출하는 접근 방식을 채택하고 있다.
JPA
- Java Persistence API
- ORM이 큰 개념이라면 JPA는 더 구체화된 스펙을 포함한다.
- 실제로 동작하는 것이 아니고 어떻게 동작해야하는지 메커니즘을 정리한 표준 명세로 생각하면 된다.
- 내부적으로 JDBC를 사용한다.
- 개발자가 직접 JDBC를 구현하면 SQL에 의존하게 되는 문제 등이 있어 개발의 효율성이 떨어지는 문제를 보완
- 개발자 대신 적절한 SQL을 생성하고 데이터베이스를 조작해서 객체를 자동 매핑하는 역할을 수행
- 하이버네이트(Hibernate), 이클립스 링크(EclipseLink), 데이터 뉴클리어스(DataNucleus)
하이버네이트
Spring Data JPA
- 하이버네이트의 기능을 더욱 편하게 사용하도록 모듈화한 것이다.
- CRUD 처리에 필요한 인터페이스를 제공한다.
- 하이버네이트의 엔티티 매니저(EntityManager)를 직접 다루지 않고 리포지토리를 정의해 사용함으로써 스프링이 적합한 쿼리를 동적으로 생성하는 방식으로 데이터베이스를 조작한다.
영속성 컨텍스트
- 애플리케이션과 데이터베이스 사이에서 엔티티와 레코드의 괴리를 해소하는 기능과 객체를 보관하는 기능을 수행한다.
- JPA는 엔티티 객체의 매핑 정보를 데이터베이스에 반영하는 작업을 수행한다.
- 세션 단위의 생명주기를 가진다.
엔티티 매니저
- 엔티티를 관리하는 객체
- 데이터베이스에 접근해서 CRUD 작업을 수행한다.
- Spring Data JPA를 사용하면 리포지토리를 사용해서 데이터베이스에 접근하는데 리포지토리에서 엔티티 매니저를 사용하는 것이다.
- 엔티티 매니저 팩토리(EntityManagerFactory)가 만든다.
엔티티 매니저 팩토리(EntityManagerFactory)
- 데이터베이스가 대응하는 객체
- 애플리케이션에서 단 하나만 생성되며, 모든 엔티티가 공유해서 사용한다.
엔티티 매니저 팩토리로 생성된 엔티티 매니저는 엔티티를 영속성 컨텍스트에 추가해서 영속 객체로 만드는 작업을 수행한다.
영속성 컨텍스트와 데이터베이스를 비교하면서 실제 데이터베이스를 대상으로 수행한다.
엔티티의 생명주기
- 비영속(New) : 영속성 컨텍스트에 추가되지 않은 엔티티 객체의 상태를 의미한다.
- 영속(Managed) : 영속성 컨텍스트에 의해 엔티티 객체가 관리되는 상태이다.
- 준영속(Detached) : 영속성 컨텍스트에 의해 관리되던 엔티티 객체가 컨텍스트와 분리된 상태이다.
- 삭제(Removed) : 데이터베이스에서 레코드를 삭제하기 위해 영속성 컨텍스트에 삭제 요청을 한 상태이다.
데이터베이스 연동
프로젝트 생성
Spring Data JPA 의존성을 추가한 후에는 별도의 설정이 필요하다.
연동할 데이터베이스 정보를 application.properties에 작성해야 한다. 밑 코드는 .properties 대신 .yaml 사용
spring:
datasource:
driverClassName: {연동하려는 데이터베이스의 드라이버 정의}
url: {데이터베이스 경로}
username: {데이터베이스 계정 정보}
password: {데이터베이스 계정 정보}
jpa:
hibernate:
ddl-auto: update
show-sql: true
properties:
hibernate:
format_sql: true
엔티티 설계
- JPA에서 엔티티는 데이터베이스의 테이블에 대응하는 클래스다.
- 엔티티에 어노테이션을 사용하면 테이블 간의 연관관계를 정의할 수 있다.
엔티티 관련 기본 어노테이션
@Entity
- 해당 클래스가 엔티티임을 명시하는 어노테이션
- 테이블과 일대일로 매칭
- 인스턴스는 매핑되는 테이블에서 하나의 레코드를 의미한다.
@Table
- 클래스의 이름과 테이블의 이름을 다르게 지정해야 하는 경우 사용한다.
- @Table(name = 값) 형태로 데이터베이스의 테이블을 명시한다.
@Id
- 테이블의 기본값 역할로 사용된다.
@GeneratedValue
- 해당 필드의 값을 어떤 방식으로 자동으로 생성할지 결정할 때 사용한다.
- GeneratedValue를 사용하지 않는 방식(직접 할당)
- 애플리케이션에서 자체적으로 고유한 기본값을 생성한 경우 사용하는 방식이다.
- 내부에 정해진 규칙에 의해 기본값을 생성하고 식별자로 사용한다.
- Auto
- @GeneratedValue의 기본 설정값
- 기본값을 사용하는 데이터베이스에 맞게 자동 생성한다.
- IDENTITY
- 기본값 생성을 데이터베이스에 위임하는 방식이다.
- 데이터베이스의 AUTO_INCREMENT를 사용해 기본값을 생성한다.
- SEQUENCE
- @SequenceGenerator 어노테이션으로 식별자 생성기를 설정하고 이를 통해 값을 자동 주입받는다.
- SequenceGenerator를 정의할 때는 name, squenceName, allocationSize를 활용한다.
- @GeneratedValue 생성기를 설정한다.
- TABLE
- 어떤 DBMS를 사용하더라도 동일하게 동작하기를 원할 경우 사용한다.
- 식별자로 사용할 숫자의 보관 테이블을 별도로 생성해서 엔티티를 생성할 때마다 값을 갱신하며 사용한다.
- @TableGenerator 어노테이션으로 테이블 정보를 설정한다.
@Column
- 자동으로 테이블 칼럼으로 매핑한다.
- name : 데이터베이스의 칼럼명을 설정하는 속성이다. 명시하지 않으면 필드명으로 지정된다.
- nullable : 레코드를 생성할 때 칼럼 값에 null 처리가 가능한지를 명시하는 속성이다.
- length : 데이터베이스에 저장하는 데이터의 최대 길이를 설정한다.
- unique : 해당 칼럼을 유니크로 설정한다.
@Transient
- 엔티티 클래스에는 선언돼 있는 필드지만 데이터베이스에서는 필요 없을 경우 이 어노테이션을 사용해 데이터베이스에서 이용하지 않게 할 수 있다.
리포지토리 인터페이스 설계
리포지토리 인터페이스 생성
- 리포지토리는 Spring Data JPA가 제공하는 인터페이스
- 엔티티가 생성한 데이터베이스에 접근하는 데 사용된다.
- 접근하려는 테이블과 매핑되는 엔티티에 대한 인터페이스를 생성하고 JpaRepository를 상속받으면 된다.
- 타입을 지정해야 하는데, 대상 엔티티를 product로 설정하고 해당 엔티티의 @Id 필드 타입으로 설정한다.
리포지토리 메서드의 생성 규칙
- FindBy : SQL문의 where절 역할을 수행하는 구문. findBy 뒤에 엔티티의 필드값을 입력해서 사용한다.
- AND, OR : 조건을 여러 개 설정하기 위해 사용한다.
- Like/NoLike : SQL 문의 like와 동일한 기능을 수행. 특정 문자를 포함하는지 여부를 조건으로 추가한다. 비슷한 키워드로 Containing, Contains, isContaing이 있습니다.
- StartsWith/StartingWith : 특정 키워드로 시작하는 문자열 조건을 설정한다.
- EndsWith/EndingWith : 특정 키워드로 끝나는 문자열 조건을 설정한다.
- IsNull/IsNotNull : 레코드 값이 Null이거나 Null이 아닌 값을 검색합니다.
- True/False : Boolean 타입의 레코드를 검색할 때 사용합니다.
- Before/After : 시간을 기준으로 값을 검색한다.
- LessThan/GreaterThan : 특정 값(숫자)을 기준으로 대소 비교를 할 때 사용한다.
- Between : 두 값(숫자) 사이의 데이터를 조회한다.
- OrderBy : SQL 문에서 order by와 동일한 기능을 수행한다.
- countBy : SQL 문의 count와 동일한 기능을 수행하며, 결괏값의 개수(count)를 추출한다.
DAO 설계
- Data Access Object
- 데이터베이스에 접근하기 위한 로직을 관리하기 위한 객체
- 비즈니스 로직의 동작과정에서 데이터를 조작하는 기능을 수행한다.
- Spring Data JPA에서는 리포지토리가 대체한다.
DAO 클래스 생성
- '인터페이스 - 구현체' 구성으로 생성
- 의존성 결합을 낮추기 위한 디자인 패턴
- 서비스 레이어에 DAO 객체를 주입받을 때 인터페이스를 선언하는 방식으로 구성할 수 있다.
- 데이터베이스에 접근하는 메서드는 리턴 값으로 데이터 객체를 전달한다.
- 일반적인 설계 원칙에서 엔티티 객체는 데이터베이스에 접근하는 계층에서만 사용
- 다른 계층으로 데이터를 전달할 때는 DTO 객체를 사용
반복되는 코드의 작성을 생략하는 방법 - 롬복(Lombok)
- 클래스를 생성할 때 반복적으로 사용하는 메서드를 어노테이션으로 대체하는 기능을 제공하는 라이브러리
@Getter, @Setter
- getter/setter 메서드를 생성한다.
생성자 자동 생성 어노테이션
- NoArgsConstructor : 매개변수가 없는 생성자를 자동 생성한다.
- AllArgsConstructor : 모든 필드를 매개변수로 갖는 생성자를 자동 생성한다.
- RequiredArgsConstructor : 필드 중 final이나 @NotNull이 설정된 변수를 매개변수로 갖는 생성자를 자동 생성한다.
@ToString
- toString() 메서드를 생성한다.
@EqualsAndHashCode
- 객체의 동등성(Equality)과 동일성(Identity)을 비교하는 연산 메서드를 생성한다.
- equals : 두 객체의 내용이 같은지 동등성을 비교한다.
- hashCode : 두 객체가 같은 객체인지 동일성을 비교한다.
@Data
- 위에 설명한 모두를 포괄하는 어노테이션이다.
'Spring' 카테고리의 다른 글
| 스프링 부트 핵심 가이드(3~5장) (1) | 2024.09.29 |
|---|---|
| 스프링 부트 핵심 가이드(1~2장) (0) | 2024.09.27 |