데이터베이스란?
데이터베이스는 데이터를 매우 효율적으로 보관하고 꺼내 볼수 있는 곳이다.데이터베이스를 사용하면 가장 큰 이점은 굉장히 많은 사람이 안전하게 데이터를 사용하고, 관리할 수 있다는 것이다.
데이터베이스 관리자,DBMS
데이터베이스를 관리하기 위한 소프트웨어를 DBMS라고 한다. 데이터베이스는 많은 사람이 공유할 수 있어야 하므로 동시 접근을 할수 있어야 한다. MySQL, 오라클은 DBMS이다.DBMS는 관리 특징에 따라서 관계형, 객체- 관계형, 도큐먼트형, 비관계형 등으로 분류한다.가장 많이 사용하는 DBMS는 관계형이다.
관계형 RDBMS(RDBMS)
RDBMS가 관계형이리고 쓰는 이유는 이 DBMS가 관계형 모델을 기반으로 하기 때문이다.RDBMS는 어렵게 생각할 필요 없이 테이블 형태로 이루어진 데이터 저장소를 생각하면된다.
H2,MySQL
H2는 자바로 작성되어 있는 RDBMS이다.스프링 부트가 지원하는 인메모리 관계형 데이타베이스이다.H2는 데이터를 다른 공간에 따로 보관하는 것이 아니라 애플리케이션 자체 내부에 데이터를 저장하는 특징이 있다. 그래서 애플리케이션을 다시 실행하면 데이터는 초기화된다. 하지만 간편하게 사용하기 좋아서 개발 시에는 테스트 용도로 많이 사용된다. 실제 서비스에는 사용하지 않고, 실제 서비스에는 MySQL과 같은 제품을 많이 사용한다.
ORM이란?
ORM은 자바의 객체와 데이터베이스를 연결해 자바언어로만 데이터베이스에 접근해서 원하는 데이터를 받아올 수 있는 프로그래밍 기법이다.
장점
- SQL을 직접 작성하지 않고 사용하는 언어로 데이터베이스에 접근할 수 있다.
- 객체지향적으로 코드를 작성할 수 있기 떄믄에 비즈니스 로직에만 집중할 수 있다.
- 데이터베이스 시스템이 추상화되어 있기 떄문에 MySQL에서 PostgreSQL로 전환한다고 해도 추가로 드는 작업이 거의 없다. 즉, 데이터베이스 시스템에 대한 종속성이 줄어든다.
- 매핑하는 정보가 명확하기 떄문에 ERD에 대한 의존도를 낮출 수 있고 유지보수할때 유리 하다.
단점
- 프로젝트의 복잡성이 커질수록 난이도도 올라간다.
- 복잡하고 무거운 쿼리는 ORM으로 해결이 불가능한 경우가 있다.
JPA와 하이버네이트?
ORM에도 여러 종류가 있다. 자바에서는 JPA를 표준으로 사용한다. JPA는 자바에서 관계형 데이터베이스를 사용하는 방식을 정의한 인터페이스 이다, 인터페이스이므로 실제 사용을 위해서는 ORM 프레임워크를 추가로 선택해야 한다. 대표적으로는 하이버네이트를 많이 사용한다. 하이버네이트는 JPA인터페이스를 구현한 구현체이자 자바용 ORM프레임워크이다. 내부적으로는 JDBC API를 사용한다. 하이버네이트 목표는 자바 객체를 통해 데이터베이스 종류에 상관없이 데이터베이스를 자유자재로 사용할 수 있게 하는 데 있다.
JPA : 자바 객체와 데이터베이스를 연결해 데이터를 관리한다. 객체 지향 도메인 모델과 데이터베이스의 다리 역할을 한다.
하이버네이트 : JPA의 인터페이스를 구현한다. 내부적으로는 JDBC API를 사용한다.
엔티티 매니저란?
엔티티
엔티티는 데이터베이스의 테이블과 매핑되는 객체를 의미한다. 엔티티는 본직적으로는 자바 객체이므로 일반 객체와 다르지 않다. 하지만 데이터베이스의 테이블과 직접 연결된다는 특징이 있어 구분지어 부른다. 즉, 엔티티는 객체이긴 하지만 데이터베이스에 영행을 미치는 쿼리를 실행하는 개체인 것이다.
엔티티 매니저
엔티티 매니저는 엔티티를 관리해 데이터베이스와 애플리케이션 사이에서 객체를 생성, 수정, 삭제하는 등의 역할을 한다. 그리고 이런 엔티티 매니저를 만드는 곳이 엔티티 매니저 팩토리이다. 데이터베이스에 여러 사용자가 접근할 수 있다. 예를 들면 회원 2명이 동시에 회원가입을 하려는 경우 엔티티 매니저는 다음과 같이 업무를 처리한다. 회원 1의 요청에 대해서 가입 처리를 할 엔티티 매니저 팩토리가 생성하면 이를 통해 가입 처리해 데이터베이스에 회원 정보를 저장한다. 회원 2도 마찬가지 이다.그리고 회원 1, 2를 위해 생성된 엔티티 매니저는 필요한 시점에 데이터베이스와 연결한 뒤에 쿼리한다. 그렇다면 스프링 부트에서 직접 엔티티 매니저 팩토리를 만들어서 관리할까? 아니다 .스프링 부트는 내부에서 엔티티 매니저 팩토리를 하나만 생성해서 관리하고 @PersistenceContext 또는 @Autowired 애너테이션을 사용해서 엔티티 매니저를 사용한다.
영속성 컨텍스트란?
엔티티 매니저는 엔티티를 영속성 컨텍스트에 저장한다는 특징이 있다. 영속성 컨텍스트는 JPA의 중요한 특징 중 하나로, 엔티티를 관리하는 가상의 공간이다. 이것이 있기 때문에 데이터베이스에서 효과적으로 데이터를 가져올 수 있고, 엔티티를 편하게 사용할 수 있는 것이다.
영속성 컨텍스트에는 1차 캐시, 쓰기 지연, 변경 감지, 지연 로딩이라는 특징이 있다. 기존에는 데이터 조작을 위해 쿼리를 직접 작성해야 했지만 스프링 부트에서는 이런 쿼리를 자바 코드로 작성하고 이를 JPA가 알아서 쿼리로 변경해주는 것이 매우 편리하다.
1차 캐시
영속성 컨텍스트는 내부에 1차 캐시를 가지고 있다. 이때 캐시의 키는 엔티티의 @Id 애너테이션이 달린 기본키 역할을 하는 식별자이며 값은 엔티티다. 엔티티를 조회하면 1차 캐시에서 데이터를 조회하고 값이 있으면 반환한다. 값이 없으면 데이터베이스에서 조회해 1차 캐시에 저장한 다음 반환한다. 이를 통해 캐시된 데이터를 조회할 때에는 데이터베이스를 거치치 않아도 되므로 매우 빠르게 데이터를 조회할 수 있다.
쓰기 지연
쓰기 지연(transactional wite-behind) 은 트랜잭션을 커밋하기 전까지는 데이터베이스에 실제로 질의문을 보내지 않고 쿼리를 모았다가 트랜잭션을 커밋하면 모았던 쿼리를 한번에 실행하는 것을 의미한다. 예를 들어 데이터 추가 쿼리가 3개라면 영속성 컨텍스트는 트랜잭션을 커밋하는 시점에 3개 쿼리를 한꺼번에 쿼리를 전송한다. 이를 통해 적당한 묶음으로 쿼리를 요청할 수 있어 데이터베이스 시스템의 부담을 줄일 수 있다.
변경 감지
트랜잭션을 커밋하면 1차 캐시에 저장되어 있는 엔티티의 값과 현재 엔티티의 값을 비교해서 변경 된 값이 있다면 변경 사항을 감지해 변경된 값을 데이터베이스에 자동으로 반영한다. 이를 통해 쓰기 지연과 마찬가지로 적당한 묶음으로 쿼리를 요청할 수 있고, 데이터베이스 시스템의 부담을 줄일 수 있다.
지연 로딩
지연 로딩(lazy loading)은 쿼리로 요청한 데이터를 애플리케 이션에 바로 로딩하는 것이 아니라 필요할 때 쿼리를 날 려 데이터를 조회하는 것을 의미한다.
공통점은 데이터베이스의 접근을 최소화해 성능을 높일 수 있다는 것이다.캐시를 하거나, 자주 쓰지 않게 하거나, 변화를 자동 감지해서 미리 준비하거나 하는 등의 방법을 쓴다.
엔티티의 상태
엔티티는 4가지 상태를 가진다. 영속성 컨텍스트가 관리하고 있지 않는 분리 상태, 영속성 컨텍스트가 관리하는 관리 상태, 영속성 컨텍스트와 전혀 관계가 없는 비영속 상태, 삭제된 상태로 나뉜다. 이 상태는 특정 메서드를 호출해 변경할 수 있는데 필요에 따라 엔티티의 상태를 조절해 데이터를 올바르게 유지하고 관리할 수 있다.
@Configuration
public class EntityManagerTest
{
final
EntityManager em;
public EntityManagerTest(EntityManager em) {
this.em = em;
}
public void example(){
//엔티티 매니저가 엔티티를 관리하지 않는 상태(비영속 상태)
Member member = new Member( 1L, "홍길동");
//엔티티가 관리되는 상태
em.persist(member);
//엔티티 객체가 분리된 상태
em.detach(member);
//엔티티 객체가 삭제된 상태
em.remove(member);
}
}
스프링 데이터 JPA란?
스프링 데이터 JPA는 스프링 데이터의 공통적인 기능에서 JPA의 유용한 기능이 추가된 기술이다. 스프링 데이터 JPA에서는 스프링 데이터의 인터페이스인 PagingAndSortingResposiory를 상속 받아 JpaRepository 인터페이스를 만들었으면, jpa를 더 편리하게 사용하는 메서드를 제공한다.
@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);
}
}
@NoArgsConstructor(access = AccessLevel.PROTECTED)//protected 기본 생성자이다.
@AllArgsConstructor
@Getter
@Entity //JPA가 관리하는 엔티티로 지정
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;
}
자동키 생성 설정 방식
AUTO | 선택한 데이터베이스 방언(dialect)에 따라 방식을 자동으로 선택(기본값) |
IDENTITY | 기본키 생성을 데이터베이스에 위임(=AUTO_INCREMENT) |
SEQUENCE | 데이터베이스 시퀀스를 사용해서 기본키를 할당하는 방법. 오라클에서 주로 사용 |
TABLE | 키 생성 테이블 사용 |
@Column 애너테이션의 속성
name | 필드와 매핑할 컬럼 이름. 설정하지 않으면 필드 이름으로 지정해준다. |
nullable | 컬럼의 null 허용 여부. 설정하지 않으면 true(nullable) |
unique | 컬럼의 유일한 값(unique) 여부. 설정하지않으면 false(non・unique) |
columnDefinition | 컬럼 정보 설정. default 값을 줄 수 있습니다. |
'Spring공부' 카테고리의 다른 글
240520_TIL (0) | 2024.05.20 |
---|---|
스프링 부트3로 블로그 만들기 (0) | 2024.05.20 |
테스트 코드 (0) | 2024.05.16 |
스프링 부트 구조 살펴보기 (0) | 2024.05.14 |
스프링 부트 (0) | 2024.05.14 |