[오늘의코딩] Step7. 백엔드 - JPA를 이용한 테이블 생성 및 조회기능까지 구현
Rosie_dev 2023. 3. 9. 15:44JAVA 17, Spring Boot 3.0.2, Gradle, MySQL, Redis로 만드는
'오늘의코딩' 메일링 서비스
메인 페이지를 하나의 Step에 묶에서 블로그 글을 쓰려고 했는데, 프론트만 다 만들어 놓고 하는 것보다 아래 하단에 보이는 서비스 나열을 백엔드로 가지고 와서 프론트를 한 번에 처리하면 편할 것 같아서, 백엔드로 데이터를 추가하고 Redis 설정하는 부분까지 설명하려고 Step을 백엔드로 나눠서 작성했다.
먼저 JPA Entity로 만드는 테이블 그리고 Repository 생성
JPA를 사용하면, Table을 직접 MySQL로 만드는게 아니라 코드로 설정이 가능하다. JPA를 우리가 SQL에 기반한 개발이 아닌 좀 더 코드 중점적인 개발을 가능하게 한다. JPA를 적극 활용하자.
먼저 테이블 생성을 위해 build.gradle에 의존성을 추가한다.
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
application.yml 에는 entity 조건에 따라 table 이 자동생성될 수 있도록 ddl-auto 설정을 create 로 해주었다. 지금은 로컬에서 개발단계에 있고 없어져도 되는 data 를 테이블이 가지고 있기 때문에 매 서버 실행시 create 로 설정되어 있지만, 향후에 테스트 서버나 운영서버에서는 ddl-auto 를 create 로 설정하기에는 테스트나 운영상에 문제가 있을 수 있음으로 반드시 조건을 확인해서 update 또는 none 처리를 해주도록 해야 한다.
spring:
jpa:
show-sql: true
hibernate:
ddl-auto: create
그 다음 Entity를 앞서 설정한 ERD를 중심으로 생성해주는데, User Entity단에 설정한 코드를 첨부했다.
@Entity - 어노테이션으로 해당 파일이 Entity임을 명시
@Table - 엔티티 클래스명과 동일한 테이블을 생성하고 매핑
@Getter, @Setter - Lombok을 사용하지 않으면, 불필요한 getter, setter 메소드를 생성해야 하는데 너무 편리한 기능
@NoArgsConstructor - 기본 생성자를 생성하기 위한 어노테이션
package com.toco.trialService.entity;
import jakarta.persistence.*;
import lombok.*;
import java.time.LocalDateTime;
@Entity
@Table(name="LOG")
@Getter
@Setter
@NoArgsConstructor
public class Log{
@Id
@Column(name="ID")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name="USER_ID")
private Long user_id;
@Column(name="LOG")
private String log;
@Column(name="TYPE")
private String type;
@Column(name="CREATED_DATE")
private LocalDateTime created_date;
public Log(Long user_id, String log, String type, LocalDateTime created_date){
this.user_id = user_id;
this.log = log;
this.type = type;
this.created_date = created_date;
}
}
이 프로젝트는 jpa 를 적극 활용하기 위해서 연관관계 mapping 처리를 해두었는데 연관관계 mapping 처리는 객체지향 프로그래밍을 위해 필요하다. 그리고 실제 코드를 간단하게 해주고 일일히 join 처리를 하지 않아도 된다는 점에서 편리성과 유지보수에 유리하다.
이번 테이블의 경우에는 단방향 연관 관계를 설계 중심으로 삼고 진행해서 불필요한 양방향 연관관계를 지양하는데 중점을 두었다. 양방향의 경우 여러 테이블과의 불필요한 연관관계로 오히려 복잡해질 수 있기 때문이다. ERD 에서도 볼 수 있듯이 단방향으로 연관관계 설정을 해두었다. 기능을 만들면서 서비스 구동시에 메서드를 좀 더 보고 연관관계를 양방향으로 할지 고민해볼 예정이다.
(import 이슈로 기존 Service 라는 명칭에서 Program 으로 변경)
이 프로젝트에서는 거의 대부분이 다대일(N:1) 관계로 매핑되어 있기 때문에 @ManyToOne조건을 활용했다.
Progress Entity에 대한 부분인데, 진행중인 서비스에 대한 내용을 가지고 올 때 각 진행상태별 사용중인 User의 정보도 같이 읽을 수 있도록 하는데 의의를 둔다. 하나의 User는 여러 개의 서비스를 신청할 수 있기 때문에 여러 개의 Progress 를 가지고 있다.
예를 들어 서비스 생성자가 해당 서비스를 삭제하려고 할 때, 서비스를 신청해서 실행중인 User 들을 파악하는데 User 의 상태가 사용중이 아닌 경우와 서비스 상태가 완료 또는 cancel 상태에서는 삭제가 가능하지만 서비스를 아직 진행중인 사람이 있을 경우 서비스 중점 사항을 편집하거나 삭제하지 못하도록 할 수 있어야 하기 때문이다.
아래처럼 User 과의 연관관계를 @ManyToOne와 @JoinColumn을 사용해서 연결할 수 있다. referencedColumnName 은 User 테이블에 join 될 컬럼 name 과 같아야 함에 유의하자.
@ManyToOne
@JoinColumn(name = "USER_ID", referencedColumnName = "ID")
private User user;
여기서 application 만 돌려도 table 이 생성되어 있는 모습을 볼 수 있다.
테이블을 Drop하고 삭제할 때, fk 문제로 SQLSyntaxErrorException 이 발생하는 경우는 아래 포스트를 참조!
2023.03.13 - [ErrorLog] - SQLSyntaxErrorException: Can't DROP '------'; check that column/key exists
테이블별로 repository 를 만들어서 연결해줘야 하는데, 한 번에 만들어 놓기 위해 기본 설정만 아래와 같이 해두었다.
package com.toco.trialService.repository;
import com.toco.trialService.entity.Log;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface LogRepository extends JpaRepository<Log, Long> {
}
테이블 생성 후 데이터 추가 테스트로 확인하기
테이블은 다 생성되었고 이제 데이터를 추가해주었다. 일단 뷰단 테스트를 위한 것이고 실제 뷰단에서 POST로 INPUT 처리하는 과정은 메인과 상세 페이지 생성 후 진행할 예정이다.
프로그램에 Insert 테스트를 하기 위해서는 mapping 될 카테고리 값이 필요해서 임의의 값을 먼저 넣어주었다.
INSERT INTO Categories(changed_date, created_date, large_category, sub_category) VALUES(now(), now(), 'large', 'sub');
테스트 코드에서 임의의 데이터를 추가해줬고, 아래와 같은 코드를 사용했다. 그리고 결과적으로 DB에 정상적으로 Insert 가 되는 것을 확인했다.
package com.toco.trialService.dbTest;
import com.toco.trialService.dto.ProgramDto;
import com.toco.trialService.entity.Program;
import com.toco.trialService.enums.Status;
import com.toco.trialService.repository.CategoriesRepository;
import com.toco.trialService.repository.ProgramRepository;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.modelmapper.ModelMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.test.context.junit.jupiter.SpringExtension;
@ExtendWith(SpringExtension.class)
@DataJpaTest
@DisplayName("프로그램 Insert Test")
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
public class InputTest {
@Autowired
private ProgramRepository programRepository;
@Autowired
private CategoriesRepository categoriesRepository;
@Test
public void rdbConnectionTest() {
ModelMapper modelMapper = new ModelMapper();
ProgramDto dto = new ProgramDto();
dto.setCategories(categoriesRepository.findById(1l).get());
dto.setImagePath("/");
dto.setStatus(Status.Expired);
dto.setUserId(1L);
dto.setProgramName("프로그램명");
dto.setProgramInfo("프로그램 Insert Test");
Program program = modelMapper.map(dto, Program.class);
System.out.println("modelMapper checker");
System.out.println(program.getProgramName());
System.out.println(program.getProgramInfo());
System.out.println(program.getCategories());
System.out.println(program.getImagePath());
programRepository.save(program);
if(programRepository.findAll().size()>0){
System.out.println("saved entity checker");
System.out.println(programRepository.findAll().get(0).getId());
}
// id 값이 있으면 저장된 것으로 간주
}
}
'Project > 오늘의 코딩 서비스 프로그램' 카테고리의 다른 글
[오늘의코딩] Step6. 백엔드 - Swagger 적용 및 ERD 수정 (0) | 2023.03.08 |
---|---|
[오늘의코딩] Step5. 프론트엔드 - 메인페이지 Carousel 만들기 (0) | 2023.03.08 |
[오늘의코딩] Step4. 프론트엔드 - Thymeleaf Layout 설정하기 (0) | 2023.03.07 |
[오늘의코딩] Step3. 백엔드 - 데이터베이스 연결 (0) | 2023.02.26 |
[오늘의코딩] Step2. 기획 - 프로젝트 설계와 구상 (0) | 2023.02.24 |
- gradle build
- 개발도서
- SQLD
- git연동
- java
- LifecycleException
- 정보처리기사 실기
- spring
- jdbc
- intellij
- 오늘의코딩
- AWS
- putty
- 북클럽
- filezila
- 실용주의프로그래머
- 노개북
- 호스팅영역
- JIRA
- 노마드코더
- ubuntu
- 기술블로그
- gradle
- 독서후기
- 배포
- EC2
- IT 5분 잡학사전
- 정보처리기사
- 웹페이지만들기
- 정보처리기사 필기
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |