ORM과 JPA
ORM : 객체지향 개념을 이용하여 관계형 데이터베이스에 적용(보존)하는 기술
즉, 객체지향 을 관계형으로 매핑하는 개념
객체지향 구조와 관계형 데이터베이스와 유사
객체지향 | 과계형 데이터베이스 | |
데이터 구조 | 클래스 | 테이블 |
데이터 | 멤버변수(데이터타입) | 컬럼(데이터타입) |
데이터 보관 | 인스턴스 | Row(레코드) |
객체지향과 관계형데이터베이스의 차이점
=> 객체지향 (행위)메서드
객체지향 : 데이터, 행위
관계형데이터베이스 : 데이터
결론
ORM은 객체지향과 관계형 사이의 변환 기법을 의미
JPA : ORM을 Java 언어에 맞게 사용할 수 있도록 제공되는 스펙
ORM이 상위 개념이고, JPA는 Java언어에 국한된 개념
JPA는 단순한 스펙이기 때문에 구현체(Hibernate 등)마다 프레임워크가 다를 수 있다
Spring Data JPA 와 JPA
스프링 부트는 JPA 구현체 중 Hibernate를 이용
Hibernate
ORM을 지원하는 오픈소스 프레임워크
단독으로 프로젝트에 적용이 가능한 독립된 프레임워크
스프링 부트 프로젝트 생성시 추가한
Spring Data JPA은 Hibernate를 쉽게 사용할 수 있도록 추가적인 API를 제공한다.
** Spring Data JPA 를 이용하여 개발 시, 필요한 코드는 두 종류
1. 엔티티 클래스 : JPA를 통하여 관리되는 객체(엔티티객체)를 위한 클래스
2. Repository : 엔티티 객체들을 처리하는 기능을 보유한 인터페이스
** Repository 인터페이스
Spring Data JPA에서 제공하는 인터페이스로 설계
스프링 내부에서 자동으로 객체를 생성하고, 실행하는 구조이기 때문에
단순히 인터페이스를 하나 정의 하기만 하면 된다 (JpaRepository 상속을 받아야한다.!!)
Hibernate를 단독으로 사용할 경우 : 모든 코드 직접 작성, 트랜잭션 처리도 직접 처리
Spring Data JPA를 이용할 경우 : 모든 코드가 자동으로 생성되기 때문에
CRUD 작업, 페이징 작업 개발을 하지 않아도 된다.
테스트를 위한 예제)
entity 패키지에 Memo 클래스를 만들었다.
package com.jdh.springboot.entity;
import lombok.*;
import javax.persistence.*;
@Entity
@Table(name = "tbl_memo")
@Data
@Builder //해당 클래스에 대한 객체 생성 처리(단, builder 어노테이션을 사용할 경우 아래 2개의 어노테이션 필수)
@AllArgsConstructor // 이 두 어노테이션이 없으면 컴파일 에러
@NoArgsConstructor
public class Memo {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long mno;
@Column(length = 200, nullable = false)
private String meno_Text;
@Transient
private int t;
}
@Entity : Spring Data JPA 사용시 필수
해당 클래스는 엔티티 클래스이고,
해당 클래스의 인스턴스들이 JPA로 괸리되는 엔티티 객체라는 것을 의미
옵션에 따라서 자동으로 테이블을 생성할 수도 있다
이 경우 해당 클래스의 멤버변수 설정에 따라서 자동으로 컬럼까지 생성된다..
@Table : @Entity 어노테이션과 함께 사용 가능
관계형 데이터베이스에서 엔티티 클래스를 어떤 테이블로 생성할 것인지에 대한 정보를 담기위한 어노테이션.
예) @Table(name = "tbl_memo") 의 경우
테이블 이름이 "tbl_memo"인 테이블을 생성
옵션을 인용하면 인덱스(indexes을 이용) 설정도 가능
@Id : @Entity 가 붙은 클래스 내에는 반드시 Primary Key(PK)에 해당하는 특정 멤버변수를 @Id로 설정해야 한다.
만약 @Id 가 붙은 멤버변수에 입력되는 값이 사용자 입력이 아니라면
자동으로 생성되는 번호를 사용하기 위해서 @GeneratedValue 어노테이션을 사용한다.
예) @GeneratedValue(strategy = GeneratoionType.IDENTITY)
PK를 자동으로 생성할 때 사용(이것을 키 생성전략이라고 부름)
@GeneratedValue(strategy = GeneratoionType.IDENTITY)
만약
연결되는 데이터 베이스가 오라클일 경우 : 별도의 번호 저장을 위한 테이블이 자동 생성
연결되는 데이터 베이스가 MySQL, MairaDB일 경우 : auto increment를 이용...
strategy 설정 값
GeneratoionType.AUTO : 기본값으로 JPA 구현체(Hibernate)가 생성 방식을 결정
GeneratoionType.IDENTITY : 사용하는 데이터베이스가 키 생성을 결정
GeneratoionType.SEQUENCE : 데이터베이스의 시퀀스를 이용하여 키를 생성. @SequenceGenerator 와 함께 사용
GeneratoionType.TABLE : 키 생성 전용 테이블을 생성하여 키 생성. @TableGenerator 와 함께 사용
@Column : 추가적인 필드(컬럼) 가 필요할 경우에 사용
이 어노테이션은 다양한 설정을 위한 옵션을 제공
name ="컬럼명"
nullable = "NULL값 허용여부(ture/false)"
length = 크기(20)
columnDefinition 을 이용하여 기본값을 설정할 수도 있다..
예) MySQL, MariaDB일 경우 : columnDefinition = "varchar(255) default 'YES'"
오라클 경우 : columnDefinition = "varchar2(255) default 'YES'"
--------------------------------------------------------------------------------------
만약 값을 사용자로부터 입력받지만, 테이블에 저장을 하지 않을 경우에는
해당 멤버변수 위에 @Transient 를 이용하여 제외 시킬 수 있다...
그 외에 JPA는 다양한 어노테이션이 있슴..
JPA 어노테이션 : import javax.persistence.*;
==============================================
Lombok이 지원하는 주요 어노테이션 : import lombok.*;
@ToString : toString메서드를 재정의
@Getter : private 변수에 대한 getter 메서드 자동 생성
@Setter : private 변수에 대한 setter 메서드 자동 생성
@Builder : 해당 클래스에 대한 객체 생성 처리 (실제 사용시엔 클래스명.builder() 를 이용)
단, 이 어노테이션을 사용할 경우에는 반드시
@AllArgsConstrutor / @NoArgsConstrutor 를 함게 설정해야한다..
그렇지 않을 경우 컴파일 시 오류 발생!!!!!!!!!!!
MemoRepository 인터페이스
public interface MemoRepository extends JpaRepository<Memo, Long> {
//Entity클래스와 Id의 타입
}
JpaRepository 클래스를 상속 받는다. 이때 타입은 <엔티티클래스 , 해당엔티티의 Id값>
SQL 없이 CRUD 테스트
insert 작업 -> save(엔티티 객체)
select 작업 : findById(키 타입) / getOne(키 타입) ** 향후 사라질 메서드
update 작업 : save(엔티티 객체)
delete 작업 : deleteById(키 타입) / delete(엔티티 객체)
insert 작업과 update 작업 => save(엔티티 객체)
JPA의 구현체가 메모리상에서 객체를 비교하고 없으면 insert / 존재하면 update로 동작
src/test/java에 새로운 패키지를 만들어서 확인
MemoRepositoryTest클래스
@SpringBootTest
public class MemoRepositoryTest {
@Autowired
MemoRepository memoRepository;
@Test
public void testClass() {
System.out.println(memoRepository.getClass().getName());
}
/** @Test
public void testInsertDummies() {
IntStream.range(1, 100).forEach(i -> {
Memo memo = Memo.builder().memo_Text("Sample TEST : " + i).build();
memoRepository.save(memo);
});
}
@Test
public void testSelect(){
Long mno = 100L;
Optional<Memo> result = memoRepository.findById(mno);
Memo memo = result.get();
}
public void testSelect2(){
Long mno = 100L;
Memo memo = memoRepository.getOne(mno);
}
**/
//페이지 처리
@Test
public void testPageDefault() {
Pageable pageable = PageRequest.of(0, 10); //0번 페이지시작 한페이지당 10개의 게시글 출력
Page<Memo> result = memoRepository.findAll(pageable);
System.out.println(result);
System.out.println("----------------------------------------");
System.out.println("총 페이지 수 : " + result.getTotalPages());
System.out.println("총 게시글 수 : " + result.getTotalElements());
System.out.println("현재 페이지 번호 : " + result.getNumber());
System.out.println("페이지당 게시글 수 : " + result.getSize());
System.out.println("다음 페이지가 존재여부 : " + result.hasNext());
System.out.println("첫번째 페이지 존재여부 : " + result.isFirst());
}
}
** 삭제(delete)와 수정(update) 코드가 빠져있다.
페이지 처리 출력값
총 페이지 수 : 10
총 게시글 수 : 99
현제 페이지 번호 : 0
페이지 크기 : 10
다음 페이지가 있는지 확인 : true
첫번째 페이지 : true
이용한 데이터 (mariaDB)
페이지 처리에서 의 핵심 Pageable (org.springframework.data.domain.Pageable)
Pageable : 페이지 처리에 필요한 정보를 전달하는 용도로 설계된 인터페이스
따라서 객체를 생성할 때
org.springframework.data.domain.PageRequest 클래스 사용
PageRequest의 static of()를 이용하여 Pageable 객체를 반환 받아야한다.
PageRequest.of( int page, int size ) : 0번 부터 시작하는 페이지 번호와 페이지당 출력된 데이터 수
PageRequest.of( int page, int size, Sort.Direction direction, String ..props)
: Sort.Direction direction : 정렬방향(방법)
String ..props : 정렬 기준 필드
PageRequest.of(int page, int size, Sort sort)
: Sort sort : 정렬 관련 정보 ( 즉, 정렬 방향과 정렬 기준 필드들을 하나로 묶은 객체)
Page<Memo> result = memoRepository.findAll(pageable);
findAll(Pageable pageable)
반환 타입 : Page<엔티티 객체 타입>
=> 2가지의 SQL을 실행
1. limit 를 사용하는 select SQL : 지정한 시작페이지 번호부터 지정한 개수를 select하기 위한 SQL
2. count() 함수를 사용하는 select SQL : 전체 레코드(엔티티) 개수를 확인하기 위한 select SQL
'Learn > KH정보교육원' 카테고리의 다른 글
[정보교육원 당산] 83일( Spring boot - Security ) (0) | 2021.07.19 |
---|---|
[KH정보교육원 당산] 79일 (Spring Boot - Thymeleaf, BootStrap) (0) | 2021.07.09 |
[KH 정보교육원 당산] 77일 ( Spring Boot - IntelliJ IDEA / MariaDB) (0) | 2021.07.07 |
[KH정보교육원 당산] 76일( JPA ) (0) | 2021.07.05 |
[KH정보교육원 당산] 75일(AJAX - To-Do-List ) (0) | 2021.07.02 |