STS 버전이 올라가면서 기존의 lombok 설정이 안되는 경우가 있다고 한다.

 

우선 경로의 한글이 없어야 하며 밑에 방법을 참고해서 진행하면 된다.

 

Spring Tool Suite 4.x에서 lombok 설치 : 네이버 블로그 (naver.com)

 

Spring Tool Suite 4.x에서 lombok 설치

Spring Tool Suite 4가 출시되어 개발 도구를 업그레이드 하면서 발생한 lombok 설치 문제를 정리한다. ...

blog.naver.com

 

Maven Repository: org.projectlombok » lombok (mvnrepository.com)

 

Maven Repository: org.projectlombok » lombok

Spice up your java: Automatic Resource Management, automatic generation of getters, setters, equals, hashCode and toString, and more! VersionVulnerabilitiesRepositoryUsagesDate1.18.x1.18.24Central725Apr, 20221.18.22Central2,249Oct, 20211.18.20Central2,386A

mvnrepository.com

 

Spring boot - 스프링부트에서 JSP 사용하기 / Gradle (tistory.com)

 

Spring boot - 스프링부트에서 JSP 사용하기 / Gradle

안녕하세요. 고코더 입니다. 스프링 부트에서 JSP는 권장사항은 아닙니다. 그래서 스타터 기본 설정에 JSP가 포함되어 있지 않습니다. 그렇기 때문에 몇 가지 추가적인 설정이 필요로 합니다. JSP

gocoder.tistory.com

 

스프링 부트는 JSP사용이 권장사항이 아니기 때문에 설정을 다시 해주어야 한다.

 

우선 JSP파일 생성할 수 있도록 기능을 다운 받아줘야하고 

 

경로 설정 또한 잡아줘야 한다.

 

권장사항은 타임리프를 이용하여 프로젝트를 진행하는 것이라고 한다.

application.propertise 파일을 작성해준다.


# 포트 설정(내장 톰캣이 사용할 포트 번호)
server.port = 8081

# view 경로 설정
spring.mvc.view.prefix = /WEB-INF/views/
spring.mvc.view.suffix = .jsp

 

작성 후 스프링 부트를 실행 시켜주면 정상 작동하는것을 확인 할 수 있다.

MySql 설치

MySQL Server 설치 (For Windows, Community) : 네이버 블로그 (naver.com)

 

MySQL Server 설치 (For Windows, Community)

이 설명서는 Windows 운영체제에서 동작하는 MySQL Server Community 8.0.11 버전을 설치하는 방법...

blog.naver.com

 

MySql 실행

시작메뉴에서 commend line client를 실행한 다음에 비밀번호를 입력하면 실행된다.

인테리제이에서 DB 설정

+ 버튼을 클릭하여 MySql을 추가해준다.

 

처음 사용하는 것이라면 드라이버 설치 팝업이 나올텐데 클릭하여 설치를 진행한다.

그 후 아래와 같이 기본 설정을 입력하고 연결 테스트를 진행한다.

 

고급 탭에서 아래와 같이 추가 설정한다.

이름: serverTimezone

값: Asia/Seoul

설정이 되었는지 확인

아래 쿼리를 실행시켜서 정상적으로 출력 되는지 확인

 

application.yml 파일에 database 연결을 해준다.

# mysql 설정        
  datasource:
    url: jdbc:mysql://localhost
    username: root
    password: root

 

gradle 추가

bulid.gradle 파일에서 설정을 추가해주어 다운 받아준다.

// mysql 사용
    runtimeOnly 'mysql:mysql-connector-java'

설정을 해준 다음 확인

아래 코드를 실행하여 정상적으로 실행되는지 확인

콘솔 화면

아래와 같은 text가 찍히는지 확인

org.hibernate.dialect.MySQL8Dialect

 

현재 사용하는 DB 생성

show databases;

create database book_manager;

 

테스트 진행을 위해서 jpa 설정 추가

#  sql문을 확인하기 위해서 추가 설정
  jpa:
    show-sql: true
    properties:
      hibernate:
#        깔끔하게 보기 위해서 설정
        format_sql: true
        show_sql: true
#        주석 확인
        use_sql_comments: true
  # 자동으로 사용되는 entity 테이블을 생성해주는 설정
    generate-ddl: true
  # 자동으로 테이블이 생성되고 제거되도록 설정
    hibernate:
      ddl-auto: create-drop

확인

 

테스트 코드 에러 처리

에러코드: JPA metamodel must not be empty!

해당 코드

package com.example.bookmanager.controller;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.data.jpa.mapping.JpaMetamodelMappingContext;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;

import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;


// MVC TEST 진행
@WebMvcTest
class HelloWorldControllerTest {

    @Autowired
    private MockMvc mockMvc;

    @Test
    void helloWorld() throws Exception{
        mockMvc.perform(MockMvcRequestBuilders.get("/hello-world"))
                .andDo(print())
                .andExpect(status().isOk())
                .andExpect(content().string("hello-world"));
    }
}
package com.example.bookmanager;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;

@SpringBootApplication
// Auditing 사용 선언하는 어노테이션
//@EnableJpaAuditing
public class BookmanagerApplication {

    public static void main(String[] args) {
        SpringApplication.run(BookmanagerApplication.class, args);
    }

}

처리방법

1. 상단에 어노테이션 추가: @MockBean(JpaMetamodelMappingContext.class)

2. 별도에 클래스를 생성하여 해결(가장 추천하는 방법)

package com.example.bookmanager.configuration;

import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;

@Configuration
@EnableJpaAuditing
public class JpaConfiguration {
}

 

'Spring > JPA' 카테고리의 다른 글

N대N 연관관계 설정 2 (중간테이블을 만들어서 사용하는 방법)  (0) 2021.08.29
N 대 N 연관관계 설정  (0) 2021.08.29
1대N 연관관계  (0) 2021.08.06
1 대 1 관계 설정하는 방법  (0) 2021.07.24
연관 관계 설정 -1  (0) 2021.07.24

이전에 작성한 내용을 중간테이블을 만들어서 사용하는 방법

N대1로 변경하여 작성하였다.

 

BookAndAuthor 클래스 작성

package com.example.bookmanager.domain;

import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.ToString;

import javax.persistence.*;

@Entity
@NoArgsConstructor
@Data
@ToString(callSuper = true)
@EqualsAndHashCode(callSuper = true)
public class BookAndAuthor extends BaseEntity{
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @ManyToOne
    private Book book;

    @ManyToOne
    private Author author;
}

 

기존 코드 수정

Author 클래스 수정

package com.example.bookmanager.domain;

import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.ToString;

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

@Entity
@NoArgsConstructor
@Data
@ToString(callSuper = true)
@EqualsAndHashCode(callSuper = true)
public class Author extends BaseEntity{
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;

    private String country;

    // N대N 관계 설정
    // stack 오버 플로우 처리
    // null 예외처리 방지 설정
//    @ManyToMany
    @OneToMany
    @JoinColumn(name = "author_id")
    @ToString.Exclude
    private List<BookAndAuthor> bookAndAuthor = new ArrayList<>();

    // ... => 배열로 받는다는 의미
    // Book 정보가 여러개 존재하면 모두 처리
    public void addBookAndAuthors(BookAndAuthor... bookAndAuthors){
        Collections.addAll(this.bookAndAuthor, bookAndAuthors);
//        if (book != null){
//            for (Book book1 : book){
//                this.books.add(book1);
//            }
//        }
    }
}

 

Book 클래스 수정

package com.example.bookmanager.domain;

import com.example.bookmanager.domain.listener.Auditable;
import com.example.bookmanager.domain.listener.MyEntityListener;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.ToString;

import javax.persistence.*;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

@Entity
@NoArgsConstructor
@Data
// 상속받은 BaseEntity를 사용하기 위해서 ToString, EqualsAndHashCode 재정의
@ToString(callSuper = true)
@EqualsAndHashCode(callSuper = true)
// 해당 객체에 사용자가 정의한 Entity Listener가 수행되도록 선언해준다.
public class Book extends BaseEntity {
    @Id
    // 테이블마다 ID값이 증가하도록 설정
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;

    private String category;

    private Long authorId;

//    private Long publisherId;

    @OneToOne(mappedBy = "book")
    // toString에서 제외, 설정하지 않으면 스택오버플로우 에러가 발생
    @ToString.Exclude
    private BookReviewInfo bookReviewInfo;

    @OneToMany
    @JoinColumn
    @ToString.Exclude
    private List<Review> reviews = new ArrayList<>();

    @ManyToOne
    @ToString.Exclude
    private Publisher publisher;

    // N대N 관계 설정
    // stack 오버 플로우 처리
    // null 예외처리 방지 설정
//    @ManyToMany
    @OneToMany
    @JoinColumn(name = "book_id")
    @ToString.Exclude
    private List<BookAndAuthor> bookAndAuthor = new ArrayList<>();

    // ... => 배열로 받는다는 의미
    // Author 정보가 여러개 존재하면 모두 처리
    public void addBookAndAuthor(BookAndAuthor... bookAndAuthors) {
        Collections.addAll(this.bookAndAuthor, bookAndAuthors);
    }

//    private String author;

//    private LocalDateTime createdAt;
//
//    private LocalDateTime updatedAt;
//
//    //@PrePersist
//    public void prePersist(){
//        this.createdAt = LocalDateTime.now();
//        this.updatedAt = LocalDateTime.now();
//    }
//
//    //@PreUpdate
//    public void preUpdate(){
//        this.updatedAt = LocalDateTime.now();
//    }
}

 

BookAndAuthorRepository 인터페이스 생성 (JPA 이용)

package com.example.bookmanager.repository;

import com.example.bookmanager.domain.BookAndAuthor;
import org.springframework.data.jpa.repository.JpaRepository;

public interface BookAndAuthorRepository extends JpaRepository<BookAndAuthor, Long> {

}

 

Test 코드 수정

package com.example.bookmanager.repository;

import com.example.bookmanager.domain.Author;
import com.example.bookmanager.domain.Book;
import com.example.bookmanager.domain.BookAndAuthor;
import org.assertj.core.util.Lists;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import javax.transaction.Transactional;

import static org.junit.jupiter.api.Assertions.*;

@SpringBootTest
class AuthorRepositoryTest {

    @Autowired
    private AuthorRepository authorRepository;
    @Autowired
    private BookRepository bookRepository;
    @Autowired
    private BookAndAuthorRepository bookAndAuthorRepository;

    @Test
    @Transactional
        // LazyInitializationException 에러 처리를 위해서 설정
    void manyToManyTest(){
        Book book1 = givenBook("책 1");
        Book book2 = givenBook("책 2");
        Book book3 = givenBook("개발책1");
        Book book4 = givenBook("개발책2");

        Author author1 = givenAuthor("martin");
        Author author2 = givenAuthor("steve");

        /* 주문 구현을 위해 추가 */
        BookAndAuthor bookAndAuthor1 = givenBookAndAuthor(book1, author1);
        BookAndAuthor bookAndAuthor2 = givenBookAndAuthor(book2, author2);
        BookAndAuthor bookAndAuthor3 = givenBookAndAuthor(book3, author1);
        BookAndAuthor bookAndAuthor4 = givenBookAndAuthor(book3, author2);
        BookAndAuthor bookAndAuthor5 = givenBookAndAuthor(book4, author1);
        BookAndAuthor bookAndAuthor6 = givenBookAndAuthor(book4, author2);

        book1.addBookAndAuthor(bookAndAuthor1);
        book2.addBookAndAuthor(bookAndAuthor2);
        book3.addBookAndAuthor(bookAndAuthor3, bookAndAuthor4);
        book4.addBookAndAuthor(bookAndAuthor5, bookAndAuthor6);

        author1.addBookAndAuthors(bookAndAuthor1, bookAndAuthor3, bookAndAuthor5);
        author2.addBookAndAuthors(bookAndAuthor2, bookAndAuthor4, bookAndAuthor6);
//        book1.addAuthor(author1);
//        book2.addAuthor(author2);

        // 공동저자로 설정
//        book3.addAuthor(author1,author2);
//        book4.addAuthor(author1,author2);
//        book3.setAuthors(Lists.newArrayList(author1, author2));
//        book4.setAuthors(Lists.newArrayList(author1, author2));

//        author1.addBook(book1, book3, book4);
//        author2.addBook(book2, book3, book4);
//        author1.setBooks(Lists.newArrayList(book1, book3, book4));
//        author2.setBooks(Lists.newArrayList(book2, book3, book4));
        // 연관 관계 설정 종료

        bookRepository.saveAll(Lists.newArrayList(book1,book2,book3,book4));
        authorRepository.saveAll(Lists.newArrayList(author1, author2));

        bookRepository.findAll().get(2).getBookAndAuthor().forEach(o -> System.out.println("3번째 책 가져오기: " + o.getAuthor()));
        authorRepository.findAll().get(0).getBookAndAuthor().forEach(o -> System.out.println("martin이 쓴 책 출력: " + o.getBook()));
//        System.out.println("3번째 책 가져오기: " + bookRepository.findAll().get(2).getAuthors());
//        System.out.println("martin이 쓴 책 출력: " + authorRepository.findAll().get(0).getBooks());
    }


    private Book givenBook(String name) {
        Book book = new Book();
        book.setName(name);

        return bookRepository.save(book);
    }

    private Author givenAuthor(String name){
        Author author = new Author();
        author.setName(name);

        return authorRepository.save(author);
    }

    private BookAndAuthor givenBookAndAuthor(Book book, Author author){
        BookAndAuthor bookAndAuthor = new BookAndAuthor();
        bookAndAuthor.setBook(book);
        bookAndAuthor.setAuthor(author);

        return bookAndAuthorRepository.save(bookAndAuthor);
    }
}

 

콘솔창 확인

3번째 책 가져오기: Author(super=BaseEntity(createdAt=2021-08-29T16:46:49.093, updatedAt=2021-08-29T16:46:49.093), id=1, name=martin, country=null)
3번째 책 가져오기: Author(super=BaseEntity(createdAt=2021-08-29T16:46:49.103, updatedAt=2021-08-29T16:46:49.103), id=2, name=steve, country=null)

martin이 쓴 책 출력: Book(super=BaseEntity(createdAt=2021-08-29T16:46:49.018, updatedAt=2021-08-29T16:46:49.018), id=1, name=책 1, category=null, authorId=null)
martin이 쓴 책 출력: Book(super=BaseEntity(createdAt=2021-08-29T16:46:49.076, updatedAt=2021-08-29T16:46:49.076), id=3, name=개발책1, category=null, authorId=null)
martin이 쓴 책 출력: Book(super=BaseEntity(createdAt=2021-08-29T16:46:49.080, updatedAt=2021-08-29T16:46:49.080), id=4, name=개발책2, category=null, authorId=null)
   create table book_and_author (
       id bigint generated by default as identity,
        created_at timestamp,
        updated_at timestamp,
        author_id bigint,
        book_id bigint,
        primary key (id)
    )

'Spring > JPA' 카테고리의 다른 글

영속성 구성을 위한 mysql 설정  (0) 2021.09.12
N 대 N 연관관계 설정  (0) 2021.08.29
1대N 연관관계  (0) 2021.08.06
1 대 1 관계 설정하는 방법  (0) 2021.07.24
연관 관계 설정 -1  (0) 2021.07.24

현업에서는 거의 사용되지 않는다.

 

예제

Author 클래스 생성

package com.example.bookmanager.domain;

import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.ToString;

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

@Entity
@NoArgsConstructor
@Data
@ToString(callSuper = true)
@EqualsAndHashCode(callSuper = true)
public class Author extends BaseEntity{
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;

    private String country;

    // N대N 관계 설정
    // stack 오버 플로우 처리
    // null 예외처리 방지 설정
    @ManyToMany
    @ToString.Exclude
    private List<Book> books = new ArrayList<>();

    // ... => 배열로 받는다는 의미
    // Book 정보가 여러개 존재하면 모두 처리
    public void addBook(Book... book){
        Collections.addAll(this.books, book);
//        if (book != null){
//            for (Book book1 : book){
//                this.books.add(book1);
//            }
//        }
    }
}

 

Book 클래스 수정 (아래 코드 추가)

    // N대N 관계 설정
    // stack 오버 플로우 처리
    // null 예외처리 방지 설정
    @ManyToMany
    @ToString.Exclude
    private List<Author> authors = new ArrayList<>();

    // ... => 배열로 받는다는 의미
    // Author 정보가 여러개 존재하면 모두 처리
    public void addAuthor(Author... author) {
        Collections.addAll(this.authors, author);
    }

 

AuthorRepository 인터페이스 생성 (JPA 사용을 위해서)

package com.example.bookmanager.repository;

import com.example.bookmanager.domain.Author;
import org.springframework.data.jpa.repository.JpaRepository;

public interface AuthorRepository extends JpaRepository<Author, Long> {

}

 

Test 코드 작성

package com.example.bookmanager.repository;

import com.example.bookmanager.domain.Author;
import com.example.bookmanager.domain.Book;
import org.assertj.core.util.Lists;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import javax.transaction.Transactional;

import static org.junit.jupiter.api.Assertions.*;

@SpringBootTest
class AuthorRepositoryTest {

    @Autowired
    private AuthorRepository authorRepository;
    @Autowired
    private BookRepository bookRepository;

    @Test
    @Transactional
        // LazyInitializationException 에러 처리를 위해서 설정
    void manyToManyTest(){
        Book book1 = givenBook("책 1");
        Book book2 = givenBook("책 2");
        Book book3 = givenBook("개발책1");
        Book book4 = givenBook("개발책2");

        Author author1 = givenAuthor("martin");
        Author author2 = givenAuthor("steve");

        book1.addAuthor(author1);
        book2.addAuthor(author2);

        // 공동저자로 설정
        book3.addAuthor(author1,author2);
        book4.addAuthor(author1,author2);
//        book3.setAuthors(Lists.newArrayList(author1, author2));
//        book4.setAuthors(Lists.newArrayList(author1, author2));

        author1.addBook(book1, book3, book4);
        author2.addBook(book2, book3, book4);
//        author1.setBooks(Lists.newArrayList(book1, book3, book4));
//        author2.setBooks(Lists.newArrayList(book2, book3, book4));
        // 연관 관계 설정 종료

        bookRepository.saveAll(Lists.newArrayList(book1,book2,book3,book4));
        authorRepository.saveAll(Lists.newArrayList(author1, author2));

        System.out.println("3번째 책 가져오기: " + bookRepository.findAll().get(2).getAuthors());
        System.out.println("martin이 쓴 책 출력: " + authorRepository.findAll().get(0).getBooks());
    }

    private Book givenBook(String name) {
        Book book = new Book();
        book.setName(name);

        return bookRepository.save(book);
    }

    private Author givenAuthor(String name){
        Author author = new Author();
        author.setName(name);

        return authorRepository.save(author);
    }
}

 

콘솔 창 결과

3번째 책 가져오기: [Author(super=BaseEntity(createdAt=2021-08-29T14:47:15.186, updatedAt=2021-08-29T14:47:15.186), id=1, name=martin, country=null), Author(super=BaseEntity(createdAt=2021-08-29T14:47:15.202, updatedAt=2021-08-29T14:47:15.202), id=2, name=steve, country=null)]
martin이 쓴 책 출력: [Book(super=BaseEntity(createdAt=2021-08-29T14:47:15.154, updatedAt=2021-08-29T14:47:15.154), id=1, name=책 1, category=null, authorId=null), Book(super=BaseEntity(createdAt=2021-08-29T14:47:15.186, updatedAt=2021-08-29T14:47:15.186), id=3, name=개발책1, category=null, authorId=null), Book(super=BaseEntity(createdAt=2021-08-29T14:47:15.186, updatedAt=2021-08-29T14:47:15.186), id=4, name=개발책2, category=null, authorId=null)]

 

 

+ Recent posts