자율학습단 스프링부트 1주차

하파타카·2023년 8월 28일
0

1일차

part1. Spring boot 개요

환경셋팅 & Spring Boot 첫 실행

Java - 자바 버전 변경하는 방법 ( JDK 8 -> JDK 17)

책에서 소개하는 대로 JDK버전을 17로 변경 후 https://start.spring.io/ 에서 위 사진과 같이 첫번째 프로젝트를 만들어 돌려보았다.
...그러나 바로 에러발생.
이유도 제대로 안나와서 뭔가 했으나 실행 시 에러가 나는 위치에 printStackTrace();를 찍어봤다.

결론은 port번호 8080은 이미 사용중이라는 에러였다.
바로 application.propertiesserver.port = 8081을 입력해 8081로 변경했다.

[SpringBoot] 열리는 Port 변경하기


static폴더에 hello.html 파일을 추가한 후 실행해보니 정상적으로 돌아간다.


2일차

Controller와 Model객체

Controller에 Model객체를 받아와 사용자에게서 속성과 속성에 대한 값을 받아올 수 있도록 함.

- FirstController -

@Controller
public class FirstController {
    @GetMapping("/hi")
    public String niceToMeetYou(Model m, String name){
        m.addAttribute("username", name);
        return "greetings";     // greetings.mustache 파일반환
    }
    @GetMapping("/bye")
    public String seeYouNext(Model m, String name){
        m.addAttribute("username", name);
        return "goodbye";
    }
}

- greetings.mustache -

<h1>{{username}}님, 반갑습니다!</h1>

- goodbye.mustache -

<h1>{{username}}님, 안녕히 가세요.</h1>



name속성의 값을 넘겨주면 이름과 뷰페이지의 내용이 정상적으로 출력됨.


만약 name속성을 넘겨주지 않을 경우 위 사진처럼 에러가 발생.

@PathVariable을 사용하면 어떨까 싶어 seeYouNext메서드만 아래와 같이 변경.

@GetMapping("/bye/{name}")
public String seeYouNext(Model m, @PathVariable String name){
    m.addAttribute("username", name);
    return "goodbye";
}

마찬가지로 http://localhost:8081/bye 로 접속하면 404오류가 발생. 아래 사진처럼 URI로 변수를 받아올 수 있다.

참고: mustache파일의 경우 빌드를 다시해야 변경점이 반영됨.
빌드 단축키: ctrl + f9


3일차

part2. 게시판 CRUD 만들기

게시글 작성 - Create



Article entity클래스의 id필드에 @GeneratedValue를 빼먹어서 숫자 자동증가가 안되어 에러발생했었음.

1. 테이블 생성

CREATE TABLE hongongspringboot.article(
	id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
	title VARCHAR(50) NOT NULL,
	content VARCHAR(1000) NOT NULL
)DEFAULT CHARSET=UTF8;

INSERT INTO hongongspringboot.board(title, content) VALUES("첫번쨰 게시글", "첫 게시글의 내용입니다.");

책에서는 H2 DB를 사용하지만 나는 MySQL을 사용하기로 함.

2. mariaDB 디펜던시 추가

// https://mvnrepository.com/artifact/org.mariadb.jdbc/mariadb-java-client
	implementation 'org.mariadb.jdbc:mariadb-java-client:3.1.4'

3. DB연결설정

- application.properties -

spring.datasource.driver-class-name=org.mariadb.jdbc.Driver
spring.datasource.url=jdbc:mariadb://localhost:3306/DB스키마이름
spring.datasource.username=접속ID
spring.datasource.password=패스워드

#update the schema with the given values.
#spring.jpa.hibernate.ddl-auto=update
#To beautify or pretty print the SQL
spring.jpa.properties.hibernate.format_sql=true
#show sql
spring.jpa.properties.hibernate.show-sql=true
#show parameter binding
logging.level.org.hibernate.type.descriptor.sql=DEBUG

logging.level.org.hibernate.SQL=DEBUG

server.servlet.encoding.force=true
server.port = 포트번호

https://wecandev.tistory.com/71
위 링크를 참고해 application.properties에 속성을 몇개 추가했는데, 몇개 주의해야할 속성이 있으므로 무엇인지 확인해놓자. (주의점은 링크 를 참고.)
spring.jpa.hibernate.ddl-auto=update속성은 사용에 주의가 필요한 것 같아 우선은 주석처리해둠.

4. controller, entity, dto 생성

@Controller
public class ArticleController {
    @Autowired
    private ArticleRepository articleRepository;

    @GetMapping("/articles/new")
    public String newArticleForm() {

        return "articles/new";
    }

    @PostMapping("/articles/create")
    public String createAricle(ArticleForm form) {
        System.out.println("form.toString() = " + form.toString());
        // 1. DTO를 entity로 변환
        Article article = form.toEntity();
        System.out.println(article.toString());

        // 2. repository로 entity를 DB에 저장
        Article saved = articleRepository.save(article);
        System.out.println(saved.toString());
        return "";
    }
}
@Entity
public class Article {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)     // 자동생성. GenerationType.IDENTITY는 기본키 생성을 DB에 맞기는 전략.
    private Long id;
    @Column
    private String title;
    @Column
    private String content;

    public Article() {}

    public Article(String title, String content) {
        this.title = title;
        this.content = content;
    }
	// toString 생성
}

책에서는 @GeneratedValue(strategy = GenerationType.IDENTITY)속성을 기본형인 @GeneratedValue로 사용하지만 아마 DB 저장이 안되는 H2를 사용해서인것으로 추측.
나의 경우 mariaDB를 사용하므로 DB에서 autoincrement를 해주도록 GenerationType.IDENTITY속성으로 사용함.

entity클래스에는 getter setter를 만들지 않음.

- ArticleForm (DTO클래스) -

public class ArticleForm {
    private String title;
    private String content;

    public ArticleForm() { }
    public ArticleForm(String title, String content) {
        this.title = title;
        this.content = content;
    }
	// getter setter toString 생성

    public Article toEntity() {
        return new Article(title, content);
    }
}

셀프체크

article을 참고하여 member 가입기능 만들기.

CREATE TABLE hongongspringboot.members(
	id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
	email VARCHAR(50) NOT NULL,
	password VARCHAR(100) NOT NULL,
	name VARCHAR(30) NOT NULL
)DEFAULT CHARSET=UTF8;

4일차

롬복으로 리팩토링하기

만약 롬복인식이 안된다면 링크를 확인하여 참고하자.
계속 값을 못받아오거나 log를 사용할수가 없어 한참 헤맷더니 롬복이 제대로 적용되지 않아서 생긴 문제였다.


5일차

게시글 읽기 - Read

CrudRepository의 기본메서드인 findById, findAll메서드를 이용함.

1. 컨트롤러에 URI 경로설정

@Slf4j
@Controller
public class ArticleController {
    @Autowired
    private ArticleRepository articleRepository;

    @GetMapping("/articles/new")
    public String newArticleForm() {
        return "articles/new";
    }

    @PostMapping("/articles/create")
    public String createAricle(ArticleForm form) {
        log.info(form.toString());
        // 1. DTO를 entity로 변환
        Article article = form.toEntity();
        System.out.println(article.toString());

        // 2. repository로 entity를 DB에 저장
        Article saved = articleRepository.save(article);
        log.info(saved.toString());
        return "redirect:/articles/" + saved.getId();
    }

    @GetMapping("/articles/{id}")
    public String show(@PathVariable Long id, Model m){
        log.info("id = " + id);
        // 1. DB에서 데이터 조회해 가져오기
        Optional<Article> articleEntity = articleRepository.findById(id);
        // 2. model에 데이터 등록하기
        m.addAttribute("article", articleEntity.get());
        // 3. 뷰 페이지 반환하기
        return "articles/show";
    }

    @GetMapping("/articles")
    public String showAll(Model m){
        // 1. DB에서 모든 데이터 가져오기
        List<Article> articleEntityList = articleRepository.findAll();
        // 2. model에 데이터 등록하기
        m.addAttribute("articleList", articleEntityList);
        // 3. 뷰 페이지 반환하기
        return "articles/index";
    }

    @GetMapping("/articles/{id}/edit")
    public String edit(){
        return "articles/edit";
    }
}

2. Repository 수정

findAll()메서드의 기본리턴형이 Iterable형이라 List형으로 변경하기 위해 Override해줌.

public interface ArticleRepository extends CrudRepository<Article, Long> {
    @Override
    ArrayList<Article> findAll();
}

3. dto, entity

- ArticleForm (dto) -

@ToString
@AllArgsConstructor
@Builder
public class ArticleForm {
    private Long id;
    private String title;
    private String content;


//    이 부분 생성자말고 빌더패턴으로 변경하고싶은데 잘안돼서 그냥놔둠
    public Article toEntity(){
        System.out.println("toEntity()에서 title = " + title +" content = " + content);
        return new Article(id, title, content);
    }
}

toEntity메서드를 Entity의 생성자를 이용하지 않고 빌더패턴을 사용하고싶으나, 현재로는 마음대로 적용되지않아 추후 변경할 예정.

- Article (entity) -

@NoArgsConstructor
@AllArgsConstructor
@ToString
@Getter
@Entity
public class Article {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)     // 자동생성. GenerationType.IDENTITY는 기본키 생성을 DB에 맞기는 전략.
    private Long id;
    @Column
    private String title;
    @Column
    private String content;
}

id값도 같이 넘겨줘도 무관.
id값을 생성자에서 빼버리면 추후 수정, 삭제기능 구현 시 게시글을 구별할 수 없음.

현재로써는 service단을 따로 만들지 않아 구조가 이렇지만 책을 따라 진행하며 service단을 추가할듯함.


의문점

  • Entity에 setter를 넣으면 안된다는건 대충 알겠는데 getter는 괜찮은건가?
  • DB에서 객체로 값을 반환받아오려면 Entity에 기본생성자가 있어야 하는듯. (모든 필드가 추가된 생성자가 필요한건 알고있음)
  • dto에 getter setter는 괜찮은가? 기본생성자는? 일단 getter는 넣어야 할 것 같긴함.
profile
천 리 길도 가나다라부터

0개의 댓글