데이터베이스?
데이터베이스는 데이터를 매우 효율적으로 보관하고 꺼내볼 수 있는 곳. 데이터베이스를 사용하면 얻을 수 있는 가장 큰 이점은 많은 사람이 안전하게 데이터를 사용하고 관리할 수 있다는 것
데이터베이스 관리자 DBMS
database management system
데이터베이스는 많은 사람이 공유 할 수 있어야 하므로 동시 접근을 할 수 있어야 한다. 이 외에도 많은 요구 사항이 있는데 DBMS는 이런 요구사항을 만족하면서도 효율적으로 데이터베이스를 관리한다.
DBMS 종류
- MySQL
- 오라클
- MariaDB등등..분류
- 관계형
- 관계 - 객체형
- 도큐먼트형
- 비관계형등등..가장 많이 사용하는 것은 관계형관계형 DBMS
- relational DBMS, RDBMS
왜 관계형?
관계형이라는 말을 쓰는 이유는 DBMS가 관계형 모델을 기반으로 하기 때문. 즉 테이블 형태로 이루어진 데이터 저장소임
예시
회원 테이블이 있다고 가정하면 각 행은 고유키 즉 아이디를 가지고 있고 이메일, 나이와 같은 회원과 관련된 값들이 들어감!
꼭 알아야할 데이터베이스 용어
테이블
데이터를 구성하기 위한 가장 기본적인 단위 테이블은 행과 열로 구분됨
행
테이블의 가로로 배열된 데이터의 집합, 반드시 고유한 기본키를 가진다 같은말로 레코드가 있다.
열
열은 각 요소에 대한 속성을 나타내고 무결성을 보장함 예를 들면 이메일 열에 숫자가 들어가거나 나이 열에 문자가 들어갈 수 없기 때문
기본키
행을 구분할 수 있는 식별자. 이 값은 테이블에서 유일해야하고 중복 값을 가질 수 없다. 또한 수정되어서는 안되고 NULL이 될 수 없다
쿼리
데이터베이스에서 CRUD를 위해서 사용하는 명령문
ORM
ORM??
Object-relational mapping
자바의 객체와 데이터베이스를 연결하는 프로그래밍 기법
만약에 age, name 컬럼에 20 홍길동이라는 값이 들어있다고 생각해보자 이걸 자바에서 사용하려면 보통 SQL문을 사용하여 데이터를 꺼내온다 하지만 이런 방법은 굉장히 번거롭고 어렵다
하지만 ORM이 있다면 데이터베이스의 값을 마치 객체처럼 사용할 수 있다. 즉 객체와 데이터베이스를 연결해 자바 언어로만 데이터베이스를 다룰 수 있게 하는 도구를 ORM이라고 한다
ORM 장점과 단점
장점
- sql을 직접 작성하지 않고 사용하는 언어로 데이터베이스에 접근할 수 있습니다.
- 객체지향적으로 코드를 작성할 수 있기 때문에 비즈니스 로직에만 집중할 수 있다.
- 데이터베이스 시스템이 추상화되어 있기 때문에 MySQL에서 PostgreSQL로 전환한다고 해도 추가로 드는 작업이 거의 없다. 즉 데이터베이스 시스템에 대한 종속성이 줄어든다
- 매핑하는 정보가 명확해서 ERD에 대한 의존도를 낮출 수 있고 유지보수할 때 유리합니다.단점
- 프로젝트의 복잡성이 커질수록 사용 난이도가 올라갑니다
- 복잡하고 무거운 쿼리는 ORM으로 해결이 불가한 경우가 있습니다.JPA와 하이버네이트
java persistence API
ORM에도 여러 종류가 있는데 자바에서는 JPA를 표준으로 한다. 자바에서 관계형 데이터베이스를 사용하는 방식을 정의한 인터페이스임. 인터페이스라서 실제로 사용을 위해서는 ORM 프레임워크를 추가로 선택해야한다. 대표적으로는 하이버네이트를 많이 사용한다. 하이버네이트는 JPA 인터페이스를 구현한 구현체이자 자바용 ORM 프레임워크임 내부적으로는 JDBC API를 사용한다.
엔티티 매니저
엔티티
엔티티는 데이터베이스의 테이블과 매핑되는 객체를 의미한다. 일반적으로는 자바 객체와 다르지 않으나 데이터베이스 테이블과 직접 연결된다는 아주 특별한 특징이 있어 구분지어 부른다. 즉 엔티티는 객체이긴 하지만 데이터베이스에 영향을 미치는 쿼리이다.
엔티티 매니저
엔티티를 관리해 데이터베이스와 애플리케이션 사이에서 객체를 CRUD하는 등의 역할을 한다. 그리고 이런 엔티티 매니저를 만드는 곳이 엔티티 매니저 팩토리임
예시
회원 2명이 동시에 회원가입을 하려는 경우
- 회원1의 요청에 대해서 가입처리를 할 엔티티 매니저를 엔티티 매니저 팩토리가 생성하면 이를 통해 가입 처리해 데이터베이스에 회원 정보를 저장한다.
- 회원2도 마찬가지
- 회원 1, 2를 위해 생성된 엔티티 매니저는 필요한 시점에 데이터베이스와 연결한 뒤에 쿼리한다
그렇다면 스프링부트도 직접 엔티티 매니저 팩토리를 만들어 관리할까? 그렇지 않다. 스프링부트는 내부에서 엔티티 매니저 팩토리를 하나만 생성해서 관리하고 @Persistence Context 또는 @Autowired 애너테이션을 사용해서 엔티티 매니저를 사용한다.
@PersistenceContext
EntityManager em;// 프록시 엔티티 매니저, 필요할때 진짜 엔티티 매니저를 호출한다.
스프링 부트는 기본적으로 빈을 하나만 생성해서 공유하므로 동시성 문제가 발생할 수 있다. 그래서 실제로는 프록시(가짜) 엔티티 매니저를 호출하고 필요할 때 데이터베이스 트랜잭션과 관련된 실제 엔티티 매니저를 호출한다
<aside> 💡 Content쉽게말해 엔티티 매니저는 JPA가 관리해서 직접 관리할 필요가 없다~
</aside>
영속성 컨텍스트
엔티티를 관리하는 가상 공간, 엔티티 매니저가 엔티티를 저장하는 곳
영속성 컨텍스트 속성
- 1차캐시
- 쓰기지연
- 변경감지
- 지연로딩1차캐시영속성 컨텍스트 내부에 1차 캐시를 가지고 있다. 이때 캐시의 키는 엔티티이 @Id애너테이션이 달린 기본키 역할을 하는 식별자이고 값은 엔티티이다 엔티티를 조회하면 1차캐시에서 데이터를 조회하고 값이 있으면 반환한다. 값이 없으면 데이터베이스에서 조회해서 1차 캐시에 저장하고 반환한다. 이를 통해서 캐시된 데이터를 조회할 때는 데이터베이스를 거치지 않아도 된다쓰기 지연
트랜잭션을 커밋하기 전까지는 데이터베이스에 실제로 질의문을 보내지 않고 쿼리를 모았다가 커밋하면 쿼리를 한번에 실행한다 데이터베이스 시스템의 부담을 줄일 수 있다
변경 감지
트랜잭션을 커밋하면 1차 캐시에 저장되어 있는 엔티티의 값과 엔티티의 값을 비교해서 변경된 값이 있다면 변경사항을 감지해 변경된 값을 데이터베이스에 자동으로 반영한다 데이터베이스의 시스템 부담을 줄일 수 있다.
지연 로딩
쿼리로 요청한 데이터를 애플리케이션에 바로 로딩하는 것이 아니라 필요할 때 쿼리를 날려 조회한다
엔티티의 상태
- 분리 : 영속성 컨텍스트가 관리하고 있지 않는 상태
- 관리 : 영속성 컨텍스트가 관리하는 상태
- 비영속 : 영속성 컨텍스트와 전혀 관계가 없는 상태
- 삭제된
package com.rowoon.studyBoot;
import jakarta.persistence.EntityManager;
import org.springframework.beans.factory.annotation.Autowired;
public class EntityManagerTest {
@Autowired
EntityManager em;
public void example(){
// 1. 비영속 상태
Member member = new Member(1, "홍길동");
// 2. 엔티티 관리
em.persist(member);
// 3. 객체 분리
em.detach(member);
//4. 객체 삭제
em.remove(member);
}
}
스프링 데이터 JPA
위의 내용은 개발자가 신경써야 할 내용이 많다. 스프링 데이터는 비즈니스 로직에 더 집중할 수 있게 데이터베이스 사용기능을 클래스 레벨에서 추상화 했다
- CRUD를 포함한 여러 메서드 포함
- 페이징 처리 기능
- 자동으로 쿼리를 빌딩하는 기능
- 데이터베이스의 특성에 맞춰 기능 확장 기술
스프링 데이터 JPA?
스프링 데이터의 공통적인 기능에서 JPA의 유용한 기술이 추가된 기술
일반 JPA에서 상태 전환
@Autowired
EntityManager em;
public void example(){
// 1. 비영속 상태
Member member = new Member(1L, "홍길동");
// 2. 엔티티 관리
em.persist(member);
스프링 데이터 JPA
@Repository
public interface MemberRepository extends JpaRepository<Member, Long> {
}
이렇게 JpaRepository 인터페이스를 우리가 만든 인터페이스에서 상속 받고 제네릭에는 엔티티이름, 엔티티 기본키 타입을 입력하면 된다
스프링 데이터 JPA에서 제공하는 메서드 사용해보기
package com.rowoon.studyBoot;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Optional;
@Service
public class MemberService {
@Autowired
MemberRepository memberRepository;
public void test(){
// 생성
memberRepository.save(new Member(1L, "A"));
// 조회
Optional<Member> member = memberRepository.findById(1L);
List<Member> allMembers = memberRepository.findAll();
// 삭제
memberRepository.deleteById(1L);
}
}
예제 코드 살펴보기
1
package com.rowoon.studyBoot;
import jakarta.persistence.*;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
@NoArgsConstructor(access = AccessLevel.PROTECTED)// 기본생성자
@AllArgsConstructor
@Getter
@Entity // 엔티티로 지정
public class Member {
@Id // id 필드를 기본키로 지정
@GeneratedValue(strategy = GenerationType.IDENTITY) // 기본키를 자동으로 1씩증가
@Column(name = "id", updatable = false)
private Long id;
@Column(name = "name", nullable = false) // name이라는 not null 컬럼과 매핑
private String name;
}
'Spring, Spring boot' 카테고리의 다른 글
템플릿엔진 - 타임리프 (0) | 2024.01.04 |
---|---|
TIL (1) | 2024.01.03 |
Spring Boot3 와 테스트 (0) | 2023.12.24 |
JPA를 활용한 기본적인 CRUD 해보기 (0) | 2023.10.26 |
트랜잭션 (1) | 2023.10.26 |