Spring Data 프레임워크_JDBC

예지성준·2024년 7월 10일

스프링프레임워크

목록 보기
5/14
post-thumbnail

Spring Data JDBC

✔ 설치

implementation 'org.springframework.data:spring-data-jdbc:3.3.1'

Spring Data api 문서


#인텔리제이 스프링프레임워크 day05

  • 초기설정
    web.xml
...
    <servlet><!--스프링에는 단 한가지의 서블릿 클래스를 제공,
     이 서블릿은 모든 요청의 창구가 된다. 서블릿은 초기화시 스프링 컨테이너를 만들어줌-->
        <servlet-name>dispatcher</servlet-name> <!--서블릿 이름 정의-->
        <servlet-class>
            org.springframework.web.servlet.DispatcherServlet
        </servlet-class>
        <init-param><!--어떤 스프링 컨테이너를 쓸 것인지 알려줘야한다.-->
            <param-name>contextClass</param-name>
            <param-value><!--handler,adapter등 담겨있는 웹전용 컨테이너-->
                org.springframework.web.context.support.AnnotationConfigWebApplicationContext
            </param-value>
        </init-param>
        <init-param>
            <param-name>contextConfigLocation</param-name><!--스프링 설정 위치 지정-->
            <param-value>
                org.choongang.config.MvcConfig <!--Spring MVC와 관련된 설정을 정의하는 클래스-->
            </param-value>
        </init-param>
    </servlet>
    
    <servlet-mapping><!--서블릿과 URL패턴 매핑-->
        <servlet-name>dispatcher</servlet-name> <!--매핑할 서블릿 이름 지정-->
        <url-pattern>/</url-pattern><!--서블릿이 매핑될 URL 패턴을 지정-->
    </servlet-mapping>
    <!--모든 URL 패턴 (/)을 dispatcher 서블릿으로 매핑, 모든 요청이 DispatcherServlet을 통해 처리됨을 의미함-->

    <filter>
        <filter-name>encodingFilter</filter-name>
        <filter-class>
            org.springframework.web.filter.CharacterEncodingFilter
        </filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>encodingFilter</filter-name>
        <url-pattern>/*</url-pattern><!--모든 경로를 의미-->
    </filter-mapping>
...
  • db설정

  • DBConfig

    • Datasource: 연결 + 커넥션 풀 설정
      @Bean(destroyMethod = "close")//스프링 컨테이너가 소멸될때 자원도 같이 해제 된다.

    • JdbcTemplate

    • PlatformTransactionManager
      @EnableTransactionManagement //트랜잭션 관련 설정 자동화

    • SqlSessionFactory
      마이바티스 관련 설정
      @MapperScan("org.choongang") //mapper 스캔 범위 설정

  • MvcConfig db 통합 설정
    @Import(DBConfig.class)


@SpringJUnitWebConfig

👩‍🏫참고)
테스트 환경에서 @SpringJUnitWebConfig 애노테이션
ExtendWith + contextConfiguration + WebAppConfiguration 기능 포함되어있는 애노테이션

HttpStatus클래스

  • Spring쪽에서 정의된 Enum상수가 정의되어있다. (응답코드)

  • 공통 예외처리 클래스

//공통 예외처리
public class CommonException extends RuntimeException{

    private HttpStatus status; //스프링쪽에서 제공하는 응답코드 enum 상수 클래스
    
    //응답코드 고정
    public CommonException(String message) {
        this(message, HttpStatus.INTERNAL_SERVER_ERROR);//500대 응답코드
    }

    public CommonException(String message, HttpStatus status){
        super(message);
        this.status = status;
    }

    //상수 조회 클래스
    public HttpStatus getStatus() {
        return status;
    }
}

✔세팅 -> 설정 클래스 추가하기(설정 자동화)

@Id

  • 기본키에 대한 부분을 명시해야함
    • @Id

쿼리 메서드

  • CrudRepository 인터페이스를 상속받은 인터페이스 Repository

🔼 mapper와 동일하게 dao을 가능하게함 (mapper역할)

쿼리를 작성하지 않았는데 실행될까 ?
MemberRepositorytest

  • 테스트1

만들어짐!

  • 테스트2 - 수정
    (id - 기본키)

    save -> 기본키가 없으면 추가, 기본키가 있으면 수정
...
@Test
    void test2(){
        Member member = Member.builder()
                .seq(1L)
                .email("user01@test.org")
                .password("12345678")
                .userName("사용자06")
                .build();

       repository.save(member);
    }

이미 있는거라 수정됨

  • 테스트3 - 조회
//기본키로 조회
    @Test
    void test3(){
        Member member = repository.findById(1L).orElse(null); //게시글이 없는 경우 등 null에 대한 처리를 많이 하기때문에 매개변수 Optional 형태로 반환값이 나옴

        System.out.println(member);
    }

  • 테스트4 - 삭제
//삭제
 @Test
    void test3(){
        Member member = repository.findById(1L).orElse(null); //게시글이 없는 경우 등 null에 대한 처리를 많이 하기때문에 매개변수 Optional 형태로 반환값이 나옴

        System.out.println(member);
        repository.delete(member);
    }

1삭제됨


  • 키값 조회 말고 원하는 값 개별 조회

인터페이스에 코드 추가
CrudRepository는 패턴을 가지고 입력하면 그거에 맞게 쿼리가 알아서 입력된다

find + (엔티티 이름) + By + 변수이름

이메일로 해당 쿼리 찾아서 조회 성공


  • 회원명으로 조회


 List<Member> findByUserNameContainingAndEmailContainingOrderByRegDtDesc(String key1, String key2);//정렬 추가
 
 ....
     @Test
    void test6(){
        List<Member> members = repository.findByUserNameContainingAndEmailContainingOrderByRegDtDesc("용자","user");
        members.forEach(System.out::println);
    }
 

메서드 명과 쿼리가 너무 긴 문제점이 있다...
위처럼 사용하지는 않음✖✖✖

이런 복잡한 형태 대신
애노테이션을 사용한다.

@Query 애노테이션

public interface MemberRepository extends CrudRepository<Member, Long> {
...
    @Query("SELECT * FROM MEMBER WHERE USER_NAME LIKE :param1 AND EMAIL LIKE :param2 ORDER BY REG_DT DESC") //param이 대체되는 부분
    List<Member> getMembers(@Param("param1")String key1, @Param("param2")String key2);
    //param1 -> key1, param2 -> key2
    ...
}   
...
 @Test
    void test7(){
        List<Member> members = repository.getMembers("%용자%","%user%");
        members.forEach(System.out::println);
    }

페이징

🔹Pageable 인터페이스

🔹PageRequest (구현 클래스)

PageNumber: 0부터 시작
PageSize:한 페이지당 출력되는 개수
sort: 정렬/ 뒤에 자동으로 ORDER BY 붙음

🔹Page 자료형
Pageable 반환값 -> Page

SELECT * FROM BOARD WHERE ... ORDER BY ... LIMIT 시작번호, 레코드개수

...
@Test
    void test8(){
        Pageable pageable = PageRequest.of(1,3);
        Page<Member> data = repository.findByUserNameContaining("용자",pageable);
    }


    @Test
    void test8(){
        Pageable pageable = PageRequest.of(0,3); //0 : 첫 페이지 부터
        Page<Member> data = repository.findByUserNameContaining("용자",pageable);
        
        List<Member> members = data.getContent();
        
        long total = data.getTotalElements(); //조회된 전체 레코드 갯수(페이지 나누지 않은)
        int pages = data.getTotalPages();
        
        members.forEach(System.out::println);
        System.out.printf("총 갯수: %d, 총 페이지 수 : %d\n",total,pages);
    }

✅ 오름차순 내림차순

import static org.springframework.data.domain.Sort.Order.asc;
import static org.springframework.data.domain.Sort.Order.desc;
...

@Test
    void test8(){
Pageable pageable = PageRequest.of(0, 3, Sort.by(desc("regDt"),asc("email")));
        Page<Member> data = repository.findByUserNameContaining("용자", pageable);
//0 : 첫 페이지 부터 , desc: 내림차순        
..
...
}

✅ @Table

@Table("CH_MEMBER") //클래스명과 테이블명을 다르게 써야할때 이 애노테이션을 사용하면 Member -> CH_MEMBER 테이블에 매칭된다.

✅ 컬럼명

profile
꽁꽁 얼어붙은 한강 위로 😺

0개의 댓글