WIL 4주차(김영현)
webWIL 4주차 리액트!
스프링 부트를 활용하여 에브리타임 백엔드 구현하기!
entity란?
- 실제 DB 테이블과 매칭될 클래스를 의미한다.
- @Entity 어노테이션을 이용하여 Entity 클래스임을 명시해줘야 한다.
- 간단한 사용법
@Id //PK로 사용될 칼럼
@Column(nullable = false)
@GeneratedValue(strategy = GenerationType.IDENTITY) // auto increment 될 계획임을 명시
private int id;
@Column(nullable = false) // null이 불가능한 칼럼
private String title;
- Builder 패턴 사용하기
- @Builder 어노테이션을 사용하여 생성자를 만들어 보자
- 장점으로는 생성자를 들어오는 모든 파라미터 경우의 수 별로 만들지 않아도 된다. 즉 불필요한 코드의 반복을 줄여준다.
- 가독성을 높여준다.
- setter를 사용하지 않게 해줌으로써 불변성을 제공한다.
- 자세한 예시 https://mangkyu.tistory.com/163
- 간단한 사용법
// 빌더 패턴 사용하여 생성자 만들기 User newUser = User.builder() .userId(userId) .password(password) .email(email) .hp(hp) .name(name) .nickname(nickname) .major(major) .build(); // entity column 설정에서 @Column(nullable = false, columnDefinition = "INT DEFAULT 0") @Builder.Default // default 값이 있다는 것을 명시해야 = 0 을 썻을때 오류가 나오지 않음. private int likeNum = 0;
- 자주 사용되는 create_data, update_date 칼럼 class로 만들기
- 해야 되는 일
- main에 @EnableJpaAuditing 어노테이션 추가하기
- class 만든 후 entity class에 extends BaseTimeEntity 추가하기
- https://webcoding-start.tistory.com/53 자세한 설명
- 사용 코드
@Getter @MappedSuperclass //JPA Entity 클래스들이 BaseTimeEntity를 상속할경우 필드들도 칼럼으로 인식하도록 함 @EntityListeners(AuditingEntityListener.class) //BaseTimeEntity클래스에 Auditing 기능을 포함시킨다. //Auditing -> Spring Data JPA에서 시간에 대해서 자동으로 값을 넣어주는 기능 public abstract class BaseTimeEntity { @CreatedDate private LocalDateTime createdAt; @LastModifiedDate private LocalDateTime updatedAt; }
Repository CRUD 외 Query문 만들기
- 해야 되는 일
- JpaRepository를 extends 하면 기본적인 crud 코드들이 있음, 만약 자신이 원하는 코드를
추가하고 싶으면 아래와 같이 추가 할 수 있음 / 같은 기능이여도 다양한 방법으로 추가 가능
아래 코드들은 제가 예전에 공부할때 사용했었던 코드들 입니다.
List<Board> findByTitle(String searchKeyword); //title을 기준으로 찾기 findBy{칼럼명}()으로 간단하게 생성 가능 List<Board> findByCategory(String searchKeyword); // 카테고리를 기준으로 찾기 Page<Board> findByTitleContaining(String searchKeyword, Pageable paging); List<Board> findByTitleContaining(String searchKeyword, Pageable paging); @Query("select b from Board b WHERE b.title like %?1% ORDER BY b.seq DESC") List<Board> queryAnnotationTest1(String searchKeyword); //위에랑 똑같음 @Query("select b from Board b WHERE b.title like %:searchKeyword% ORDER BY b.seq DESC") List<Board> queryAnnotationTest2(@Param("searchKeyword") String searchKeyword); //특정값 조회하기 @Query("select b.seq, b.title, b.writer from Board b WHERE b.title like %:searchKeyword% ORDER BY b.seq DESC") List<Object[]> queryAnnotationTest3(@Param("searchKeyword") String searchKeyword); //나만의 쿼리 만들어 사용하기 @Query(value="select seq, title, writer from board WHERE title like '%'||?1||'%' ORDER BY seq DESC", nativeQuery = true) List<Object[]> queryAnnotationTest4( String searchKeyword); @Query("select b from Board b ORDER BY b.seq DESC") List<Board> queryAnnotationTest5(Pageable paging);
test code 작성
- save code
Optional<User> newUser = userRepository.findById(1); // findById 를 이용할시에 Id에 해당하는 row가 없을 수도 있기 때문에 ifPresent 코드가 없으면 상관은 없지만 노란 밑줄이 그어짐 newUser.ifPresent(getUser -> { // newUser가 있다면 newBoard = Board.builder() .userId(getUser) .title("테스트 게시글") .content("테스트 게시글 입니다.") .category(2) .commentNum(3) .build(); }); boardRepository.save(newBoard);
- get code
Optional<Board> newBoard = boardRepository.findById(2); newBoard.ifPresent(getBoard->{ System.out.println("user id : " + getBoard.getUserId()); System.out.println("title : " + getBoard.getTitle()); System.out.println("content : " + getBoard.getContent()); System.out.println("category : " + getBoard.getCategory()); System.out.println("isSecret : " + getBoard.getIsSecret()); System.out.println("likeNum : " + getBoard.getLikeNum()); System.out.println("comment Num : " + getBoard.getCommentNum()); System.out.println("is hot : " + getBoard.getIsHot()); System.out.println("created at : " + getBoard.getCreatedAt()); System.out.println("updated at : " + getBoard.getUpdatedAt()); });
- delete code
public void deleteBoardTest(){ boardRepository.deleteById(4); //id에 해당하는 row 삭제 }
- update code
Optional<Board> changeBoard = boardRepository.findById(2); String changeTitle = "바뀐 제목"; changeBoard.ifPresent(getBoard ->{ getBoard.setTitle(changeTitle); boardRepository.save(getBoard); }); //가져와서 제목만 바꾼후 다시 저장 //id가 pk이므로 sava를 사용해도 이미 있으면 update됨. //다시 가져와서 출력해보기 Optional<Board> newBoard = boardRepository.findById(2); newBoard.ifPresent(getBoard->{ System.out.println("user id : " + getBoard.getUserId()); System.out.println("title : " + getBoard.getTitle()); System.out.println("content : " + getBoard.getContent()); System.out.println("category : " + getBoard.getCategory()); System.out.println("isSecret : " + getBoard.getIsSecret()); System.out.println("likeNum : " + getBoard.getLikeNum()); System.out.println("comment Num : " + getBoard.getCommentNum()); System.out.println("is hot : " + getBoard.getIsHot()); System.out.println("created at : " + getBoard.getCreatedAt()); System.out.println("updated at : " + getBoard.getUpdatedAt()); });
헷갈렸던 부분
DB 생성
귀신에 홀렸는지 DB를 먼저 만들어야 한다고 생각해서 직접 sql문을 작성하여 db를 작성했더니 @ManyToOne에서 FK를 제대로 인식하지 못하는 문제가 생김..
@JoinColumn 어노테이션을 사용하여 해결하려 했지만
또 새로운 문제가 생겨서 아예 db를 삭제 후 테스트 코드로 db를 생성하니 오류 해결..
내 머리를 안믿고 자동화된 코드를 믿기로 함!
테스트 코드를 이용하여 db를 생성하고 진행 하자!
다음 목표
- 각종 기능들 만들어보기