반응형

https://velog.io/@52future/DataGrip

 

데이터베이스 IDE DataGrip 학생 인증하여 무료로 사용하기

DataGrip 이라는 데이터베이스 관리 툴을 소개합니다.JetBrains에서 제공하는 이 툴은 다양한 DBMS 와의 연동이 가능하고 .학교 이메일이 있다면 학생 인증을 통해서 무료 라이선스로 사용 가능하다는

velog.io

학생계정으로 가입하고 datagrip 사용했습니다!

그리고 처음에 vscode로 진행했는데 스프링은 intellj로 따라가는게 좋을 것 같아요.. datagrip 설치할 때 만든 학생계정으로 intellj ultimate 설치하기 !

 

1. 부트 프로젝트 생성 및 확인

apiserver 프로젝트를 먼저 생성하고 진행했다.

 

데이터베이스 설정이 되어있지 않아서 처음에 실행을 하면 오류가 난다.

따라서 apidb라는 이름으로 먼저 데이터베이스를 생성하고

 

CREATE USER 'apidbuser'@'localhost' IDENTIFIED BY 'apidbuser';
CREATE USER 'apidbuser'@'%' IDENTIFIED BY 'apidbuser';

GRANT ALL PRIVILEGES ON apidb.* TO 'apidbuser'@'localhost';
GRANT ALL PRIVILEGES ON apidb.* TO 'apidbuser'@'%';

SQL 스크립트를 실행한다.

  • 'apidbuser'@'localhost': 이 사용자는 로컬에서만 접속할 수 있음
  • 'apidbuser'@'%': 이 사용자는 원격에서 접속할 수 있도록 설정됨
    • 두 사용자 모두 비밀번호는 'apidbuser'로 설정
  • 'apidbuser'@'localhost' 사용자에게 apidb 데이터베이스에 대한 모든 권한을 부여
  • 'apidbuser'@'%' 사용자에게도 같은 권한을 부여

 

datagrip으로 만들어둔 apidb 연결



SELECT now();

현재 시간을 확인해서 설정이 잘 되었는지 확인

 

 

 

spring.application.name=apiserver

spring.datasource.driver-class-name=org.mariadb.jdbc.Driver

spring.datasource.url=jdbc:mariadb://localhost:3306/apidb

spring.datasource.name=apidbuser
spring.datasource.password=apidbuser

application.properties 작성 -> 가장 기본적인 설정을 추가한 것

커넥션 풀 : 미리 만들어놓고 재사용하는 것

 

나는 실행이 안 돼서 main을 지정하고 실행함

 

spring.application.name=apiserver

spring.datasource.driver-class-name=org.mariadb.jdbc.Driver

spring.datasource.url=jdbc:mariadb://localhost:3306/apidb

spring.datasource.username=apidbuser
spring.datasource.password=apidbuser

spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.format_sql=true
spring.jpa.show-sql=true

logging.level.com.zaxxer=trace
  • JDBC 드라이버 클래스와 MariaDB 데이터베이스의 URL을 지정
  • 데이터베이스에 접속할 때 사용할 데이터베이스 사용자 이름과 비밀번호 지정
  • Hibernate: 애플리케이션 실행 시 데이터베이스 스키마를 어떻게 처리할지 결정하는 설정
    • update: 기존 테이블에 변경 사항이 있으면 이를 업데이트함

 

logging.level.com.zaxxer=trace

로그로 잘 설정되었는지 확인

 

2. 엔티티 클래스 만들기

엔티티는 클래스와 객체를 구분해서 만들어야 함

 

domain 패키지에 Todo 클래스 생성

 

package org.zerock.apiserver.domain;

import jakarta.persistence.*;
import lombok.*;

import java.time.LocalDateTime;

@Entity
@ToString
@Getter
@Builder
@AllArgsConstructor
@NoArgsConstructor

@Table(name="tbl_todo")
public class Todo {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long tno;

    private String title;

    private String content;

    private boolean complete;

    private LocalDateTime dueDate;
}

JPA(Entity)로 사용되는 Todo 클래스

Todo 엔티티는 데이터베이스 테이블과 매핑되며, 각 필드는 테이블의 컬럼으로 매핑됨

 

실행하면 위와 같이 tbl_todo 테이블이 생성됨

 

업데이트를 하면 테이블이 2개가 생기기 때문에 정리를 해야 함

todo 테이블을 drop함

 

interface를 생성

 

3. 엔티티의 테스트

build.gradle에서 Lombok을 테스트 코드에서 사용할 수 있도록 설정하기 위해 아래 두 코드를 추가해야 함

testCompileOnly 'org.projectlombok:lombok'
testAnnotationProcessor 'org.projectlombok:lombok'

 

 

    @Test
    public void testInsert() {

        Todo todo = Todo.builder()
                .title("Title")
                .content("Content...")
                .dueDate(LocalDate.of(2024, 10, 01).atStartOfDay())
                .build();

        Todo result = todoRepository.save(todo);

        log.info(result);
    }

testInsert() 테스트 메서드는 Todo 엔티티 객체를 생성하고 이를 데이터베이스에 저장한 후 저장된 결과를 로그에 출력함

 

@Test
    public void testRead() {

        Long tno = 1L;

        Optional<Todo> result = todoRepository.findById(tno);

        Todo todo = result.orElseThrow();

        log.info(todo);
    }

testRead() 메서드는 특정 tno(Primary Key)를 사용해 데이터베이스에서 Todo 엔티티를 조회함

 

 

package org.zerock.apiserver.domain;

import jakarta.persistence.*;
import lombok.*;

import java.time.LocalDateTime;

@Entity
@ToString
@Getter
@Builder
@AllArgsConstructor
@NoArgsConstructor

@Table(name="tbl_todo")
public class Todo {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long tno;

    private String title;

    private String content;

    private boolean complete;

    private LocalDateTime dueDate;

    public void changeTitle(String title) {
        this.title = title;
    }

    public void changeContent(String content) {
        this.content = content;
    }

    public void changeComplete(boolean complete) {
        this.complete = complete;
    }

    public void changeDueDate(LocalDateTime dueDate) {
        this.dueDate = dueDate;
    }
}

 

이제 업데이트를 진행하기 위해 Todo.java에서 setter 설정을 해준다.

각 필드를 변경하기 위한 것!

@Test
    public void testUpdate() {
        //먼저 로딩하고 엔티티 객체를 변경 (setter
        Long tno = 1L;

        Optional<Todo> result = todoRepository.findById(tno);

        Todo todo = result.orElseThrow();

        todo.changeTitle("Update Title");
        todo.changeContent("updated content");
        todo.changeComplete(true);

        todoRepository.save(todo);
    }

먼저 select할 때 sql문이 실행되고 save할 때 다시 확인을 한다. 그리고 update문이 실행되는 것을 확인할 수 있다.

 

그리고 다시 read 테스트를 진행하면 업데이트가 된 것을 확인할 수 있다.

 

4. 목록(페이징)처리 구현

@Test
    public void testPaging() {

        // 페이지 번호는 0부터 시작함
        Pageable pageable = PageRequest.of(0, 10, Sort.by("tno").descending());

        Page<Todo> result = todoRepository.findAll(pageable);

        log.info(result.getTotalElements());

        log.info(result.getContent());
    }

페이지 데이터를 가지고 올 때 데이터가 10개가 되지 않아서 count query를 보내지 않는다.

 

@Test
    public void testInsert() {

        for (int i = 0; i < 100; i++) {

            Todo todo = Todo.builder()
                    .title("Title"+i)
                    .content("Content..."+i)
                    .dueDate(LocalDate.of(2024, 10, 01).atStartOfDay())
                    .build();

            Todo result = todoRepository.save(todo);

            log.info(result);
        }
    }

따라서 for문을 추가함

이제 위와 같이 count가 나타나는 것을 확인할 수 있음

 

다시 testpaging을 실행해 보면 출력이 하나 더 생기고 전체 데이터는 101건이 있는 것을 알 수 있음

 

5. Querydsl 설정하기

해외에서는 jooq를 많이 사용하지만 우리나라는 querydsl을 대부분 사용한다.

 

https://cafe.naver.com/gugucoding

 

구멍가게코딩단 : 네이버 카페

안녕하세요? 구멍가게 코딩단의 활동을 위한 카페입니다.

cafe.naver.com

카페 자료를 보고 gradle 코드를 수정함

 

compile.Jave를 실행하면 QTodo가 생성되어야 함

QueryDSL을 사용하는 경우 자동으로 생성되는 클래스

Q로 시작하는 클래스는 QueryDSL이 엔티티 클래스(Todo)에 대해 생성한 메타데이터 클래스이며, 이를 통해 타입 안전한 쿼리를 작성할 수 있음

 

package org.zerock.apiserver.repository.search;

import org.springframework.data.domain.Page;
import org.zerock.apiserver.domain.Todo;

public interface TodoSearch {

    Page<Todo> search1();
}

TodoSearch 인터페이스 생성

동적 처리

package org.zerock.apiserver.repository.search;

import com.querydsl.jpa.JPQLQuery;
import lombok.extern.log4j.Log4j2;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.repository.support.QuerydslRepositorySupport;
import org.zerock.apiserver.domain.QTodo;
import org.zerock.apiserver.domain.Todo;

@Log4j2
public class TodoSearchImpl extends QuerydslRepositorySupport implements TodoSearch {

    protected TodoSearchImpl() {
        super(Todo.class);
    }

    @Override
    public Page<Todo> search1() {

        log.info("search1..................");

        QTodo todo = QTodo.todo;

        JPQLQuery<Todo> query = from(todo);

        query.where(todo.title.contains("1"));

        Pageable pageable = PageRequest.of(0, 10, Sort.by("tno").descending());
        this.getQuerydsl().applyPagination(pageable, query);

        query.fetch(); //목록 데이터

        query.fetchCount();

        return null;
    }
}

TodoSearchImpl.java

    @Test
    public void testSearch1(){

        todoRepository.search1();

    }

test 코드 추가 후 실행

count까지 출력되는 것을 확인

=> TodoSearchImpl 클래스는 TodoSearch 인터페이스를 구현하며, QueryDSL을 사용해 동적 쿼리를 실행함

페이징된 결과를 반환하고 있음

TodoRepositoryTests는 데이터베이스 작업을 테스트하는 메서드들을 정의하고 있는데, testSearch1()을 추가하여 검색 기능을 확인함

 

반응형

'Web' 카테고리의 다른 글

5. 상품 API 서버 구성하기 - 1  (0) 2024.10.08
4. 리액트와 API 서버 통신  (0) 2024.10.06
3. 스프링부트와 API 서버 - 2  (0) 2024.10.02
2. React-Router  (0) 2024.09.24
1. 개발환경 설정  (0) 2024.09.24