프로그래밍/Java

spring boot 와 JPA + mysql 사용한 두개 테이블 조인 Insert

소행성왕자 2023. 8. 23. 17:29

프로젝트 구조

build.gradle

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath "gradle.plugin.com.ewerk.gradle.plugins:querydsl-plugin:1.0.10"
    }
}

plugins {
    id 'java'
    id 'war'
    id 'org.springframework.boot' version '2.7.14'
    id 'io.spring.dependency-management' version '1.1.2'
    id 'com.ewerk.gradle.plugins.querydsl' version '1.0.10' // Querydsl 플러그인 추가
}

group = 'com.naya'
version = '0.0.1-SNAPSHOT'

java {
    sourceCompatibility = '11'
}

configurations {
    compileOnly {
        extendsFrom annotationProcessor
    }
}

repositories {
    mavenCentral()
}

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
    implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
    implementation 'org.springframework.boot:spring-boot-starter-web'
    compileOnly 'org.projectlombok:lombok'
    developmentOnly 'org.springframework.boot:spring-boot-devtools'
    runtimeOnly 'com.mysql:mysql-connector-j'
    runtimeOnly 'org.mariadb.jdbc:mariadb-java-client'
    annotationProcessor 'org.projectlombok:lombok'
    providedRuntime 'org.springframework.boot:spring-boot-starter-tomcat'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
    implementation 'nz.net.ultraq.thymeleaf:thymeleaf-layout-dialect'
    //implementation 'com.github.gavlyukovskiy:p6spy-spring-boot-starter:1.5.6'
    implementation 'javax.validation:validation-api'
    implementation 'com.querydsl:querydsl-jpa:5.0.0'
}

def querydslDir = 'src/main/generated'

querydsl {
    library = "com.querydsl:querydsl-apt"
    jpa = true
    querydslSourcesDir = querydslDir
}

sourceSets{
    main{
        java{
            srcDirs = ['src/main/java', querydslDir]
        }
    }
}

compileQuerydsl{
    options.annotationProcessorPath = configurations.querydsl
}

configurations {
    querydsl.extendsFrom compileClasspath
}

tasks.named('test') {
    useJUnitPlatform()
}
위 코드는 Gradle 빌드 스크립트 파일로, Spring Boot 프로젝트를 구성하는 데 사용됩니다. 

Buildscript Dependencies: 이 섹션은 Gradle 빌드 스크립트에서 사용할 플러그인 및 의존성을 정의합니다. 여기에서는 com.ewerk.gradle.plugins.querydsl 플러그인을 추가하고 있습니다. 이 플러그인은 Querydsl을 프로젝트에 통합하는 데 도움을 줍니다.

Plugins: Spring Boot와 관련된 플러그인 및 버전을 설정합니다. 이 프로젝트에서는 Spring Boot 2.7.14 버전을 사용하고 있으며, io.spring.dependency-management 플러그인을 사용하여 의존성 관리를 설정하고 있습니다.

Project Information: 프로젝트 그룹, 버전 및 Java 소스 호환성을 설정합니다.

Configurations: 다양한 Gradle 구성을 정의합니다. 여기에서는 compileOnly 구성을 annotationProcessor에서 확장하고 있습니다.

Repositories: Maven 중앙 저장소에서 의존성을 다운로드 받을 수 있도록 설정합니다.

Dependencies: 프로젝트에서 사용하는 모든 의존성을 정의합니다. Spring Boot Starter, Thymeleaf, Lombok, MySQL, MariaDB 등과 같은 의존성을 추가하고 있습니다.

QueryDSL Configuration: Querydsl 관련 설정을 정의합니다. Querydsl을 사용하여 JPA 엔터티를 생성하기 위해 필요한 구성을 제공합니다. querydslDir 변수는 생성된 Querydsl 소스 코드가 위치하는 디렉토리를 지정합니다.

SourceSets: 메인 소스 세트를 정의하고, Querydsl 소스 코드 디렉토리를 메인 소스에 추가합니다.

CompileQuerydsl: Querydsl을 컴파일하는 데 필요한 옵션을 설정합니다.

Configurations: querydsl 구성을 compileClasspath에서 확장하도록 설정합니다.

Test Task Configuration: 테스트 실행을 위한 설정을 지정합니다.

이 스크립트는 Spring Boot 기반의 프로젝트를 구성하고, Querydsl을 사용하여 JPA 엔터티를 생성하고 쿼리를 작성할 수 있도록 설정하는 데 필요한 기본적인 구성을 포함하고 있습니다.

application.yml

server:
  address: localhost
  port: 8080

spring:
  jpa:
    show-sql: true
    database: mysql
    properties:
      hibernate:
        ddl-auto: create
        format_sql: true


  #      create	기존 테이블 삭제 후 다시 생성
  #      create-drop	create와 같음, 종료 시점에 테이블 drop
  #      update	변경분만 반영(운영 db 사용 x) -> 추가만됨, 지우는건 x
  #      validate	엔티티와 테이블이 매핑 되었는지 확인
  #      none	사용 x

  #       개발 초기 create or update
  #       테스트 서버 update or validate
  #       운용 validate or none



  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/dbname?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Seoul
    username: username
    password: password

  thymeleaf:
    cache: false
    prefix: file:src/main/resources/templates/
    suffix: .html
  devtools:
    restart:
      enabled: true
위의 코드는 Spring Boot 애플리케이션의 설정 파일인 application.yml (또는 application.properties)의 내용을 나타냅니다. 이 설정 파일은 Spring Boot 애플리케이션의 동작 방식 및 환경 구성을 정의하는 데 사용됩니다.

Server Configuration:

server.address: 애플리케이션이 바인딩할 IP 주소를 지정합니다. 여기서는 localhost로 설정되어 로컬 호스트에서만 액세스할 수 있습니다.
server.port: 애플리케이션의 HTTP 포트를 지정합니다. 여기서는 8080으로 설정되어 8080번 포트에서 실행됩니다.
Spring Data JPA Configuration:

spring.jpa.database: 사용할 데이터베이스 종류를 설정합니다. 여기서는 MySQL을 사용하고 있습니다.
spring.jpa.hibernate.ddl-auto: Hibernate의 DDL 자동 생성 기능을 설정합니다. 여기서는 create로 설정되어 애플리케이션을 시작할 때마다 데이터베이스 스키마를 삭제하고 다시 생성합니다. 이 옵션은 주로 개발 및 테스트 단계에서 사용됩니다.
spring.jpa.hibernate.format_sql: SQL 쿼리를 예쁘게 출력할지 여부를 설정합니다. true로 설정되어 SQL 쿼리가 예쁘게 출력됩니다.
spring.jpa.show-sql: 쿼리를 로그로 출력할지 여부를 설정합니다. true로 설정되어 JPA가 실행하는 SQL 쿼리가 로그로 출력됩니다.
Thymeleaf Configuration:

thymeleaf.cache: Thymeleaf 템플릿 캐싱을 활성화 또는 비활성화합니다. false로 설정되어 템플릿 캐싱이 비활성화됩니다.
thymeleaf.prefix: Thymeleaf 템플릿 파일이 위치한 디렉토리를 지정합니다. 여기서는 상대 경로 file:src/main/resources/templates/로 설정되어 템플릿 파일이 src/main/resources/templates/ 디렉토리에 있다고 가정합니다.
thymeleaf.suffix: Thymeleaf 템플릿 파일의 확장자를 지정합니다. .html로 설정되어 HTML 템플릿 파일을 사용합니다.
Spring Boot DevTools Configuration:

devtools.restart.enabled: Spring Boot DevTools의 자동 재시작 기능을 활성화 또는 비활성화합니다. true로 설정되어 코드 변경 시 애플리케이션이 자동으로 재시작됩니다.
이러한 설정을 통해 Spring Boot 애플리케이션은 웹 서버의 주소와 포트를 구성하고, JPA와 Hibernate 설정을 지정하여 데이터베이스와의 상호작용을 관리하며, Thymeleaf를 사용하여 뷰 템플릿을 처리하며, 개발 도구를 통해 애플리케이션을 쉽게 개발하고 테스트할 수 있게 됩니다.

1. 엔티티 클래스 생성

먼저 두 개의 테이블과 매핑되는 엔티티 클래스를 생성합니다. 

  • Members.java
  • Board.java

Members와 Board 테이블을 조인하려고 한다면 다음과 같은 엔티티 클래스를 생성할 수 있습니다.

Board.java

package com.jpatest.jpatest.entity;

import lombok.AccessLevel;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;

import javax.persistence.*;
import java.time.LocalDateTime;

@Entity
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Getter
public class Board {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "board_id")
    private Long id;                    // 번호
    private String title;               // 제목
    private String content;             // 내용

    @CreatedDate
    private LocalDateTime regDate;      // 등록일

    @LastModifiedDate
    private LocalDateTime uptDate;      // 수정일

    private Long viewCount;             // 조회수
    private String delYn;               // 삭제 여부

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "member_id")
    private Members members;

    @Builder

    public Board(String title, String content, Members members) {
        this.title = title;
        this.content = content;
        this.viewCount = 0L;
        this.delYn = "N";
        this.members = members;
        this.regDate = LocalDateTime.now();
        this.uptDate = LocalDateTime.now();
    }
}
위의 코드는 JPA(Java Persistence API)를 사용하여 데이터베이스와 상호작용하는 데 사용되는 엔티티 클래스를 나타냅니다. 
이 클래스는 게시판 게시물과 관련된 정보를 저장하는 데 사용됩니다.

@Entity: 이 어노테이션은 클래스가 JPA 엔티티임을 나타냅니다. JPA는 이 클래스와 데이터베이스 테이블을 매핑합니다.

@NoArgsConstructor(access = AccessLevel.PROTECTED): 이 어노테이션은 인자 없는 생성자를 생성합니다. AccessLevel.PROTECTED로 설정되어 외부에서 직접 생성되는 것을 방지하며, JPA는 프록시 객체를 생성할 때 이 생성자를 사용합니다.

@Getter: Lombok 프로젝트의 어노테이션으로, 게시물 엔티티 클래스의 필드에 대한 Getter 메서드를 자동으로 생성합니다.

@Id: 이 어노테이션은 엔티티 클래스의 기본 키(primary key)를 나타냅니다. @GeneratedValue 어노테이션과 함께 사용하여 자동으로 생성되는 값을 가지는 필드임을 지정합니다.

@GeneratedValue(strategy = GenerationType.IDENTITY): 이 어노테이션은 기본 키 값이 자동으로 생성되는 전략을 설정합니다. 여기서는 데이터베이스의 자동 증가(AUTO_INCREMENT) 기능을 사용하여 기본 키 값을 생성합니다.

@Column(name = "board_id"): 이 어노테이션은 엔티티 클래스의 필드와 데이터베이스 테이블의 컬럼 간 매핑을 지정합니다. name 속성은 데이터베이스 테이블의 컬럼 이름을 지정합니다.

나머지 필드들은 게시물 엔티티의 속성을 나타냅니다. 각각의 의미는 다음과 같습니다:

title: 게시물의 제목을 나타내는 문자열 필드.
content: 게시물의 내용을 나타내는 문자열 필드.
regDate: 게시물의 등록일을 나타내는 LocalDateTime 필드.
uptDate: 게시물의 수정일을 나타내는 LocalDateTime 필드.
viewCount: 게시물의 조회수를 나타내는 Long 필드.
delYn: 게시물의 삭제 여부를 나타내는 문자열 필드.
members: 회원과 게시물 간의 다대일(N:1) 관계를 나타내는 필드. @ManyToOne 어노테이션을 사용하여 매핑되며, @JoinColumn 어노테이션을 통해 외래 키를 지정합니다.
@Builder: Lombok 프로젝트의 어노테이션으로, 빌더 패턴을 자동으로 생성합니다. 
이를 통해 객체를 생성할 때 가독성 있고 유연한 방식으로 객체를 초기화할 수 있습니다. 
Members 객체와 관련된 필드만 설정하고 나머지 필드는 기본값으로 초기화됩니다.

이 클래스는 게시판 게시물과 관련된 정보를 저장하고, 데이터베이스와의 상호작용을 위한 JPA 엔티티로 사용됩니다.

 

Members.java

package com.jpatest.jpatest.entity;

import lombok.AccessLevel;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;

@Entity
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Getter
public class Members {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "member_id")
    private Long id;
    private String username;
    private String password;
    private String phoneNo;
    private int age;

    @OneToMany(mappedBy = "members")
    private List<Board> boardList = new ArrayList<>();

    @Builder
    public Members(String username, int age) {
        this.username = username;
        this.age = age;
    }
}
위의 코드는 JPA(Java Persistence API)를 사용하여 데이터베이스와 상호작용하는 데 사용되는 Members 엔티티 클래스를 나타냅니다. 이 클래스는 회원 정보를 저장하는 데 사용됩니다.

@Entity: 이 어노테이션은 클래스가 JPA 엔티티임을 나타냅니다. JPA는 이 클래스와 데이터베이스 테이블을 매핑합니다.

@NoArgsConstructor(access = AccessLevel.PROTECTED): 이 어노테이션은 인자 없는 생성자를 생성합니다. AccessLevel.PROTECTED로 설정되어 외부에서 직접 생성되는 것을 방지하며, JPA는 프록시 객체를 생성할 때 이 생성자를 사용합니다.

@Getter: Lombok 프로젝트의 어노테이션으로, Members 엔티티 클래스의 필드에 대한 Getter 메서드를 자동으로 생성합니다.

@Id: 이 어노테이션은 엔티티 클래스의 기본 키(primary key)를 나타냅니다. @GeneratedValue 어노테이션과 함께 사용하여 자동으로 생성되는 값을 가지는 필드임을 지정합니다.

@GeneratedValue(strategy = GenerationType.IDENTITY): 이 어노테이션은 기본 키 값이 자동으로 생성되는 전략을 설정합니다. 여기서는 데이터베이스의 자동 증가(AUTO_INCREMENT) 기능을 사용하여 기본 키 값을 생성합니다.

@Column(name = "member_id"): 이 어노테이션은 엔티티 클래스의 필드와 데이터베이스 테이블의 컬럼 간 매핑을 지정합니다. name 속성은 데이터베이스 테이블의 컬럼 이름을 지정합니다.

나머지 필드들은 회원 엔티티 클래스의 속성을 나타냅니다. 각각의 의미는 다음과 같습니다:

username: 회원의 이름을 나타내는 문자열 필드.
password: 회원의 비밀번호를 나타내는 문자열 필드.
phoneNo: 회원의 전화번호를 나타내는 문자열 필드.
age: 회원의 나이를 나타내는 정수 필드.
boardList: 회원과 게시물 간의 일대다(1:N) 관계를 나타내는 필드. @OneToMany 어노테이션을 사용하여 매핑되며, mappedBy 속성을 통해 관계의 주인을 설정합니다.
@Builder: Lombok 프로젝트의 어노테이션으로, 빌더 패턴을 자동으로 생성합니다. 이를 통해 객체를 생성할 때 가독성 있고 유연한 방식으로 객체를 초기화할 수 있습니다. Members 객체와 관련된 필드만 설정하고 나머지 필드는 기본값으로 초기화됩니다.

이 클래스는 회원 정보를 저장하고, 데이터베이스와의 상호작용을 위한 JPA 엔티티로 사용됩니다.

 

2. Repository 인터페이스 생성 

각 엔티티에 대한 Repository 인터페이스를 생성합니다.

BoardRepository.java

package com.jpatest.jpatest.repository;

import com.jpatest.jpatest.entity.Board;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface BoardRepository extends JpaRepository<Board, Long> {

}


MemberRepository.java

package com.jpatest.jpatest.repository;

import com.jpatest.jpatest.entity.Members;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface MemberRepository extends JpaRepository<Members, Long> {

}
위 코드는 Spring Data JPA를 사용하여 데이터베이스와 상호작용하기 위한 두 개의 리포지토리 인터페이스인 BoardRepository와 MemberRepository를 정의하고 있습니다.

BoardRepository:

JpaRepository<Board, Long>를 확장하고 있습니다. 이는 Spring Data JPA에서 제공하는 JpaRepository를 활용하여 Board 엔티티에 대한 데이터 액세스를 위한 메서드들을 제공합니다.
@Repository 어노테이션은 Spring에게 이 인터페이스가 리포지토리 역할을 하는 빈(bean)임을 알려줍니다. Spring은 이 빈을 자동으로 생성하고 관리합니다.
Board 엔티티와 관련된 CRUD(Create, Read, Update, Delete) 및 데이터베이스 조작 작업을 위한 메서드를 JpaRepository에서 상속받아 사용할 수 있습니다.
MemberRepository:

JpaRepository<Members, Long>를 확장하고 있습니다. 이는 Spring Data JPA에서 제공하는 JpaRepository를 활용하여 Members 엔티티에 대한 데이터 액세스를 위한 메서드들을 제공합니다.
@Repository 어노테이션은 Spring에게 이 인터페이스가 리포지토리 역할을 하는 빈(bean)임을 알려줍니다. Spring은 이 빈을 자동으로 생성하고 관리합니다.
Members 엔티티와 관련된 CRUD(Create, Read, Update, Delete) 및 데이터베이스 조작 작업을 위한 메서드를 JpaRepository에서 상속받아 사용할 수 있습니다.
이렇게 정의된 리포지토리 인터페이스들을 사용하면 데이터베이스와의 상호작용을 위한 코드를 직접 작성하지 않고, JpaRepository에서 제공하는 메서드들을 활용하여 데이터를 쉽게 읽고 쓸 수 있습니다. Spring Data JPA는 개발자들이 데이터 액세스 작업을 훨씬 편리하게 처리할 수 있도록 도와줍니다.

 

3. controller 생성

  • BoardController.java
package com.jpatest.jpatest.controller;

import com.jpatest.jpatest.dto.BoardDto;
import com.jpatest.jpatest.dto.MemberDto;
import com.jpatest.jpatest.entity.Board;
import com.jpatest.jpatest.entity.Members;
import com.jpatest.jpatest.repository.BoardRepository;
import com.jpatest.jpatest.repository.MemberRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

import java.util.List;

@Controller
public class BoardController {

    @Autowired
    BoardRepository boardRepository;

    @Autowired
    MemberRepository memberRepository;

    @GetMapping("/add_member")
    public String addMember(){

        String username = "지화자";
        int age = 20;

        Members members = Members.builder()
                .username(username)
                .age(age)
                .build();
        memberRepository.save(members);

        return "board/list";
    }

    @GetMapping("/add_member_dto")
    public String addMemberDto(){

        String username = "문지방";
        int age = 25;

        MemberDto memberDto = new MemberDto(username, age);
        Members members = memberDto.toEntity();
        memberRepository.save(members);

        return "board/list";
    }

    @GetMapping("/add_board")
    public String addBoard(){

        String title = "타이틀이지1";
        String content = "내용1";

        List<Members> membersList = memberRepository.findAll();
        Members members = membersList.get(0);

        Board board = Board.builder()
                .title(title)
                .content(content)
                .members(members)
                .build();
        boardRepository.save(board);

        return "board/list";
    }

    @GetMapping("/add_board_dto")
    public String addBoardDto(){

        String title = "타이틀이지1";
        String content = "내용1";

        List<Members> membersList = memberRepository.findAll();
        Members members = membersList.get(0);

        BoardDto boardDto = new BoardDto(title, content);
        Board board = boardDto.toEntity(members);
        boardRepository.save(board);

        return "board/list";
    }

}
위 코드는 Spring Boot 애플리케이션에서 웹 요청을 처리하는 BoardController 클래스를 정의하고 있습니다. 이 컨트롤러는 회원과 게시판 데이터를 생성하고 관리하기 위한 다양한 엔드포인트를 제공합니다.

@Controller 어노테이션:

이 클래스가 컨트롤러 역할을 하는 것을 나타내며 Spring에 의해 관리되는 빈(bean)으로 등록됩니다.
@Autowired 어노테이션:

의존성 주입을 통해 BoardRepository와 MemberRepository 빈을 주입받습니다.
/add_member 엔드포인트:

회원 데이터를 추가하는 엔드포인트입니다.
회원의 이름과 나이를 받아 Members 엔티티를 생성하고 저장합니다.
/add_member_dto 엔드포인트:

회원 데이터를 추가하는 엔드포인트입니다.
회원의 이름과 나이를 MemberDto 객체를 통해 받아와서 Members 엔티티로 변환하여 저장합니다.
DTO(Data Transfer Object) 패턴을 사용하여 데이터 전송과 관련된 작업을 처리합니다.
/add_board 엔드포인트:

게시판 데이터를 추가하는 엔드포인트입니다.
게시글의 제목과 내용을 받아와서, 회원 데이터를 조회한 후 Board 엔티티를 생성하고 저장합니다.
/add_board_dto 엔드포인트:

게시판 데이터를 추가하는 엔드포인트입니다.
게시글의 제목과 내용을 BoardDto 객체를 통해 받아와서, 회원 데이터를 조회한 후 Board 엔티티로 변환하여 저장합니다.
DTO(Data Transfer Object) 패턴을 사용하여 데이터 전송과 관련된 작업을 처리합니다.
각 엔드포인트는 클라이언트의 요청을 받아 해당 동작을 수행하고, 그 결과로 "board/list" 뷰 페이지를 반환합니다. 이렇게 구현된 컨트롤러를 통해 웹 애플리케이션에서 회원과 게시글을 추가할 수 있게 됩니다.

 

4. DTO 생성

  • BoardDto
  • MemberDto
BoardDto.java

package com.jpatest.jpatest.dto;

import com.jpatest.jpatest.entity.Board;
import com.jpatest.jpatest.entity.Members;
import lombok.Data;

import java.time.LocalDateTime;

@Data
public class BoardDto {
    private Long id;
    private String title;
    private String content;
    private Long viewCount;
    private LocalDateTime redDate;
    private LocalDateTime uptDate;

    public BoardDto(String title, String content) {
        this.title = title;
        this.content = content;
    }


    public Board toEntity(Members members) {
        return Board.builder()
                .title(title)
                .content(content)
                .members(members)
                .build();
    }
}
위 코드는 데이터 전송 객체(Data Transfer Object, DTO)를 정의한 클래스인 BoardDto를 나타냅니다. DTO는 주로 데이터의 전달과 관련된 역할을 하는 객체로, 엔티티 클래스와 웹 뷰 간 데이터 전달을 쉽게 하기 위해 사용됩니다.

@Data 어노테이션:

Lombok 라이브러리를 사용하여 Getter, Setter, equals, hashCode, toString 등의 메서드를 자동으로 생성합니다.
멤버 변수:

id: 게시글의 고유 식별자
title: 게시글의 제목
content: 게시글의 내용
viewCount: 조회수
redDate: 등록 날짜
uptDate: 수정 날짜
생성자:

BoardDto(String title, String content): 제목과 내용을 매개변수로 받는 생성자입니다.
toEntity 메서드:

Members 엔티티를 매개변수로 받아서, Board 엔티티로 변환하여 반환하는 메서드입니다.
Board 엔티티를 빌더 패턴을 사용하여 생성하고, title, content, 그리고 받아온 members를 설정한 후 엔티티를 반환합니다.
이렇게 정의된 BoardDto 클래스는 주로 웹 요청에서 받은 데이터를 가공하거나 엔티티로 변환하는 데 사용됩니다. 예를 들어, 웹 폼에서 입력한 데이터를 BoardDto 객체로 수신하고, 이를 toEntity 메서드를 통해 Board 엔티티로 변환하여 JPA를 사용하여 데이터베이스에 저장할 수 있습니다.

 

MemberDto.java

package com.jpatest.jpatest.dto;

import com.jpatest.jpatest.entity.Members;
import lombok.Data;

@Data
public class MemberDto {
    private Long id;
    private String username;
    private String password;
    private String phoneNo;
    private int age;


    public MemberDto(String username, int age) {
        this.username = username;
        this.age = age;
    }

    public Members toEntity() {
        return Members.builder()
                .username(username)
                .age(age)
                .build();
    }
}
위 코드는 데이터 전송 객체(Data Transfer Object, DTO)를 정의한 클래스인 MemberDto를 나타냅니다. DTO는 주로 데이터의 전달과 관련된 역할을 하는 객체로, 엔티티 클래스와 웹 뷰 간 데이터 전달을 쉽게 하기 위해 사용됩니다.

@Data 어노테이션:

Lombok 라이브러리를 사용하여 Getter, Setter, equals, hashCode, toString 등의 메서드를 자동으로 생성합니다.
멤버 변수:

id: 회원의 고유 식별자
username: 회원의 이름 또는 사용자명
password: 회원의 비밀번호
phoneNo: 회원의 전화번호
age: 회원의 나이
생성자:

MemberDto(String username, int age): 사용자명(username)과 나이(age)를 매개변수로 받는 생성자입니다.
toEntity 메서드:

Members 엔티티로 변환하는 메서드입니다.
Members 엔티티를 빌더 패턴을 사용하여 생성하고, 받아온 username과 age를 설정한 후 엔티티를 반환합니다.
이렇게 정의된 MemberDto 클래스는 주로 웹 요청에서 받은 데이터를 가공하거나 엔티티로 변환하는 데 사용됩니다. 예를 들어, 웹 폼에서 입력한 회원 정보 데이터를 MemberDto 객체로 수신하고, 이를 toEntity 메서드를 통해 Members 엔티티로 변환하여 JPA를 사용하여 데이터베이스에 저장할 수 있습니다.

 

5. 웹서버 시작시 테이블 과 데이터 자동 생성

아래 경로에 insert 쿼리문 만들어 저장합니다. 

resources/import.sql

INSERT INTO members (username, age, phone_no) VALUES('사용자1','31','016-2222-2222');
INSERT INTO members (username, age, phone_no) VALUES('사용자2','32','016-2222-2222');
INSERT INTO members (username, age, phone_no) VALUES('사용자3','33','016-2222-2222');
INSERT INTO members (username, age, phone_no) VALUES('사용자4','34','016-2222-2222');
INSERT INTO members (username, age, phone_no) VALUES('사용자5','35','017-2222-2222');
INSERT INTO members (username, age, phone_no) VALUES('사용자6','36','018-2222-2222');
INSERT INTO members (username, age, phone_no) VALUES('사용자7','46','019-2222-2222');

 

6. Talend API tester 로 확인

members 테이블

 

board 테이블

 

 

 

참고 https://aamoos.tistory.com/671?category=856312 

 

[Spring Jpa] 4. 게시판 만들기 - Entity 생성, 빌드패턴, P6 spy 설정 (InteliJ+Spring Data Jpa+QueryDsl+H2+타임리

이전글 보기 https://aamoos.tistory.com/670 [Spring Jpa] 3. 게시판 만들기 - H2 Database 연결하기 이전글 보기 https://aamoos.tistory.com/669 [Spring Jpa] 2. 게시판 만들기 - bootstrap5 적용하기 이전글 보기 https://aamoos.tis

aamoos.tistory.com

 

Controller 의 비지니스 로직을 Service 로 이동해본다.

프로젝트 구조

BoardController.java

package com.jpatest.jpatest.controller;

import com.jpatest.jpatest.service.BoardService;
import com.jpatest.jpatest.service.MemberService;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
public class BoardController {

    private final BoardService boardService;
    private final MemberService memberService;

    public BoardController(BoardService boardService, MemberService memberService) {
        this.boardService = boardService;
        this.memberService = memberService;
    }

    @GetMapping("/add_member")
    public String addMember(){

        memberService.write();

        return "board/list";
    }

    @GetMapping("/add_member_dto")
    public String addMemberDto(){

        memberService.writeDto();

        return "board/list";
    }

    @GetMapping("/add_board")
    public String addBoard(){

        boardService.write();

        return "board/list";
    }

    @GetMapping("/add_board_dto")
    public String addBoardDto(){

        boardService.writeDto();

        return "board/list";
    }

}
package com.jpatest.jpatest.service;

public interface BoardService {
    void write();

    void writeDto();
}



package com.jpatest.jpatest.service;

import com.jpatest.jpatest.dto.BoardDto;
import com.jpatest.jpatest.dto.MemberDto;
import com.jpatest.jpatest.entity.Board;
import com.jpatest.jpatest.entity.Members;
import com.jpatest.jpatest.repository.BoardRepository;
import com.jpatest.jpatest.repository.MemberRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class BoardServiceImpl implements BoardService {

    @Autowired
    BoardRepository boardRepository;

    @Autowired
    MemberRepository memberRepository;

    @Override
    public void write() {

        String title = "타이틀이지1";
        String content = "내용1";

        List<Members> membersList = memberRepository.findAll();
        Members members = membersList.get(0);

        Board board = Board.builder()
                .title(title)
                .content(content)
                .members(members)
                .build();
        boardRepository.save(board);
    }

    @Override
    public void writeDto() {
        String title = "타이틀이지77";
        String content = "내용77";

        List<Members> membersList = memberRepository.findAll();
        Members members = membersList.get(0);

        BoardDto boardDto = new BoardDto(title, content);
        Board board = boardDto.toEntity(members);
        boardRepository.save(board);
    }
}
package com.jpatest.jpatest.service;

public interface MemberService {
    void write();

    void writeDto();
}


package com.jpatest.jpatest.service;

import com.jpatest.jpatest.dto.MemberDto;
import com.jpatest.jpatest.entity.Members;
import com.jpatest.jpatest.repository.BoardRepository;
import com.jpatest.jpatest.repository.MemberRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class MemberServiceImpl implements MemberService {

    @Autowired
    BoardRepository boardRepository;

    @Autowired
    MemberRepository memberRepository;


    @Override
    public void write() {

        String username = "지화자";
        int age = 20;

        Members members = Members.builder()
                .username(username)
                .age(age)
                .build();
        memberRepository.save(members);
    }

    @Override
    public void writeDto() {
        String username = "문지방";
        int age = 25;

        MemberDto memberDto = new MemberDto(username, age);
        Members members = memberDto.toEntity();
        memberRepository.save(members);
    }
}