+ 00 00 0000

Have any Questions?

05_Simple Coding – Backend – JPA – 기본 요약

05_Simple Coding – Backend – JPA – 기본 요약

📃 요약

실무에서는 MVC 디자인 패턴 속해서 스프링부트를 사용해 코딩을 진행함. 파일관리 시 파일을 용도에 맞게 정리하듯이 MVC 디자인 패턴도 패키지 및 클래스를 용도에 맞게 분류해서 코딩을 진행함

요소 기술 :

– Basic : java & spring boot

📃 기술 구현

스펙 :

- intellij
- java
- spring boot

📃 JPA :

- DB 에 접속하여 CRUD를 실행하는 라이브러리
- SQL 문을 개발자가 작성하는 것이 아닌 JPA 가 자동으로 SQL 문을 생성해줌
- 코딩 생산성 향상
    1) 간단하고 반복되는 쿼리를 작성할 필요없이 JPA 함수만 실행하면 자동으로 SQL 문을 생성해서 실행해줌
    2) 개발자가 직접 SQL 문을 작성해서 실행하는 기능도 포함됨

과거 DB 코딩 역사 (현재 포함) :

1) JDBC 라이브러리를 이용해 문자열에 직접 SQL 문을 넣어 실행했음
2) Mybatis 의 등장으로 문자열 대신 xml 파일안에 SQL 문을 작성하는 형태로 변경(가독성 향상)
3) Mybatis 로 가독성은 향상되었으나 단순 쿼리가 주로 작성되는 프로젝트의 경우 일일이 SQL 문을 작성해야 하므로 코딩생산성이 하락했음
4) 최근에 JPA 의 등장으로 단순한 쿼리는 자동으로 생성되는 JPA 기능을 이용하고 단순하지 않은 쿼리는 직접 개발자가 작성(JPQL, Querydsl) 하는 것으로 코딩 생산성을 향상 시킴 

DB & JPA 환경 설정 :

- build.gradle : JPA 라이브러리 추가 (프로젝트 생성시 추가했다면 생략)
    // 오라클 19c
    implementation 'com.oracle.database.jdbc:ucp:19.14.0.0'
    implementation 'com.oracle.database.security:oraclepki:19.14.0.0'
    implementation 'com.oracle.database.security:osdt_cert:19.14.0.0'
    implementation 'com.oracle.database.security:osdt_core:19.14.0.0'

//  todo: log4jdbc 설정
    implementation 'org.bgee.log4jdbc-log4j2:log4jdbc-log4j2-jdbc4.1:1.16'

    // JPA 라이브러리
    implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
    // Oracle jdbs 드라이버
    runtimeOnly 'com.oracle.database.jdbc:ojdbc8'
    ...

📃 Entity 클래스:

- 엔티티 클래스 : 정보를 저장하는 용도의 자바 클래스
- DB 테이블의 구조와 거의 일치해야 하며 컬럼명은 속성명(필드명)과 일치함
- 주로 @Entity, @Table, @SequenceGenerator 등의 아래의 어노테이션을 사용해 작성함

@Entity :

- 대상 클래스를 참고하여 DB에 물리 테이블을 생성함

@Table(name = “테이블명”) :

- 자동 생성 시 물리 테이블명으로 생성됨

@SequenceGenerator :

- Oracle DB 시퀀스 생성시 사용할 속성들

@DynamicInsert :

- insert 시 null 인 컬럼 제외해서 sql 문 자동 생성함

@DynamicUpdate :

- update 시 null 인 컬럼 제외해서 sql 문 자동 생성함

@Id :

- 기본키가 지정될 속성 -> DB에 기본키를 자동으로 만들어줌

@Column(columnDefinition = “컬럼타입(개수)”) :

- DB에 자동 생성될 테이블의 컬럼정보 직접 지정

📃 Repository 인터페이스 :

- JPA 는 자동으로 SQL 을 생성해 주는 기본 CRUD 함수들이 있음
하지만 라이브러리 추가만으로 사용할 수 있는것이 아니라, JpaReposigory 인터페이스를 상속 받아야만 비로소 사용이 가능함
예 :
@Repository
public interface DeptRepository extends JpaRepository<Dept, Integer> {
}

Paging 처리

- 목적 : 전체 데이터를 화면에 출력하면 데이터 비약적으로 많다면 성능이 매우 떨어지므로 몇건씩 끊어서 보여주어 화면 로딩시간과 조회 속도를 높이는 것
- 페이징 대표 변수 : 
    1) page = 현재페이지, 
    2) size = 1 페이지 당 보여줄 데이터 수  
- 페이징 대표 객체 : 
    1) 매개변수 페이징 객체 : Pageable
    2) 리턴될 페이징 객체   : Page<객체자료형>
- 클라이언트로 전송할 데이터 : Map 자료구조를 이용

Page findAll(Pageable pageable) 함수 :

- 전체 조회 select 쿼리를 자동으로 만들어 주는 함수
- paging 처리시 매개변수로 Pageable 객체를 포함해야 페이징 처리가 됨
- 결과는 Page 객체로 리턴됨
    1) Page 객체의 일부 데이터만 Map 자료구조에 넣어 클라이언트로 전송함
    2) Page 객체 주요 getter 함수
        - getContent()       : 쿼리 결과 배열 가져오기
        - getNumber()        : 현재 페이지 번호 가져오기
        - getTotalElements() : 전체 페이지 번호 가져오기
        - getTotalPages()    : 전체 페이지 개수 가져오기

    3) 페이징 처리 공식 : 블럭시작페이지번호 , 블럭끝페이지번호 구하기
        - 예) [이전] 0 1 2 [다음]  => 1블럭
              [이전] 3 4 5 [다음] => 2블럭
              [이전] 6 7 8 [다음] => 3블럭
        - 1블럭 : 0(블럭시작페이지번호) ~ 2(블럭끝페이지번호)  , 2블럭 : 3(블럭시작페이지번호) ~ 5(블럭끝페이지번호), 3블럭 : 6(블럭시작페이지번호) ~ 8(블럭끝페이지번호)
        - 공식 : 블럭시작페이지번호 = (Math.floor(현재페이지번호/1페이지당개수)) * 1페이지당개수
            1) 현재페이지 2, 1페이지당 개수 3 이라면 계산 => Math.floor(2/3) * 3 = 0 (블럭시작페이지번호)
            2) 현재페이지 5, 1페이지당 개수 3 이라면 계산 => Math.floor(5/3) * 3 = 3 (블럭시작페이지번호)
        - 공식 : 블럭 끝페이지 번호 = 블럭 시작페이지번호 + 1페이자당개수 - 1
            (0부터 시작하므로 1 빼기)

findById(매개변수) 함수 :

- 매개변수로 상세 조회 select 쿼리를 자동으로 만들어 주는 함수

save(객체변수) 함수 :

- 객체변수에 기본키 속성(필드)이 없으면 자동으로 Insert 쿼리문이 생성되고,
기본키 속성이 있으면 자동으로 Update 쿼리문이 생성됨

delete(매개변수) 함수 :

- 매개변수로 delete 쿼리를 자동으로 만들어 주는 함수

📃 JPQL :

- JPA 에서 개발자가 직접 쿼리문을 작성할 수 있게 하는 기능
- @Query() , 쿼리메소드 2가지 방식이 있음
- 2가지 방식은 모두 JpaRepository 인터페이스를 상속받은 클래스안에서 함수 정의를 해야함

쿼리메소드 :

- 함수명으로 쿼리문을 작성하는 방식(낙타표기법 사용)
- 쿼리문이 길어지면 함수명도 굉장히 길어져 가독성이 떨어지는 단점이 있음
- 간단한 쿼리문 작성시 사용
- 다양한 상세 활용은 구글링으로 사용법 조회 권고
사용법 : 
    findAll - 전체조회
    OrderBy - 정렬(Order by)
    Dno     - 대상 컬럼명
    Desc    - 내림차순 [Asc]

예 :
@Repository
public interface DeptRepository extends JpaRepository<Dept, Integer> {

//    todo: 1) 전체 조회 + 정렬(내림차순)
    List<Dept> findAllByOrderByDnoDesc();
}

@Query : 오라클 쿼리

- sql 문을 직접 작성
- 직관적이어서 좋으나 , 문자열로 작성해야 해서 가독성은 떨어짐 
- nativeQuery = true : 오라클 쿼리 사용시 옵션 적용 
- nativeQuery 생략 시 객체 쿼리가 사용됨
- sql 문 안의 :변수명 : sql 문이 완성될때 대체될 변수값
- countQuery 옵션 : Paging 처리시 전체 개수가 필요한 데 그 값을 구하는 count 쿼리문
- 복잡한 분석함수 또는 집계함수를 사용해야 할때 사용
- 실무에서는 querydsl 로 대체해서 많이 사용하고 있음
 사용법 : 
    @Query(value = "select * from 테이블명 where 컬럼명 = :변수명 "
            , countQuery = "select count(*) from 테이블명 where 컬럼명 = :변수명 "
            , nativeQuery = true)
    Page selectByDname(@Param("변수명") String 변수명, Pageable pageable);

 // dname like 검색 : ( 오라클 쿼리 )
    @Query(value = "SELECT TD.* FROM TB_DEPT TD WHERE TD.DNAME LIKE '%' || :dname || '%' 
    , countQuery = "SELECT count(TD.*) FROM TB_DEPT TD WHERE TD.DNAME LIKE '%' || :dname || '%' 
    ", nativeQuery = true)
    Page selectByDname(@Param("dname") String dname, Pageable pageable);

@Query : 객체 쿼리

- sql 문을 직접 작성
- 테이블명 대신 객체명, 컬럼명 대신 속성(필드)명, * 대신 객체 별칭 사용함
- nativeQuery 생략 시 객체 쿼리가 사용됨
- sql 문 안의 :변수명 : sql 문이 완성될때 대체될 변수값
- countQuery 옵션 : 페이징시 오라클 쿼리와 달리 생략됨
- 이것을 쓰는 것보다 querydsl 을 사용하는 것을 추천함
 사용법 : 
    @Query(value = "select 별명 from 객체명 별명 where 속성명 = :변수명 "
            , countQuery = "select count(*) from 객체명 별명 where 속성명 = :변수명 "
            , nativeQuery = true)
    Page selectByDname(@Param("변수명") String 변수명, Pageable pageable);

예 :
 // dname like 검색 : ( 오라클 쿼리 )
    @Query(value = "SELECT td FROM Dept td WHERE td.dname LIKE '%' || :dname || '%' ")
    Page selectByDname(@Param("dname") String dname, Pageable pageable);

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다