[error] @Builder 애너테이션 사용시 NullPointerException 에러
Input은 이렇게 책 검색 정보 API 갖고 오고,
Board의 정보도 같이 입력해서 폼 제출한 후, 각각의 엔터티에 저장시켜주려고 했다.
엔터티는 이런 형식임
이때 외래키가 공유되므로 이미지 파일 올리면서 책 정보도 올리고 나눔글 정보까지 같이 올라가야만 한다.
근데 각각의 외래키에 정보를 하나씩 넣기보다 한 테이블에서 입력을 하고 저장하면 다른 테이블에는 자동으로 올라갈 수 있도록
연관관계 메서드를 만들어서 넣는 것이 좋다!!
그래서 만든 연관관계 메서드는
Books 엔터티에 Image 추가 메서드,
// 연관관계 메서드
// 이미지를 올리면 Books의 이미지리스트에 추가가 되면서 또 Images 엔티티에 추가가 된다.
public void addImage(Images image) {
imagesList.add(image);
image.setBooks(this);
}
Boards 엔터티에 Book 추가 메서드
// 연관관계 메서드
// 책 한 권을 올리면 Boards에 Book 추가되면서 Books엔티티에도 추가
public void addBook(Books book) {
book.setBoards(this);
this.getBooksList().add(book);
}
이렇게 만들어두고 service단에서 이 메서드를 불러들였다!
@Transactional
public void uploadIntoDB(List<String> imgUrlList, InsertBookDTO bookDTO, InsertBoardDTO boardDTO) {
// board로 메시지값 받아와서 build
Boards boards = Boards.builder()
.message(boardDTO.getMessage())
.build();
// 그것을 DB에 저장
Boards board = boardRepository.save(boards);
// bookDTO에서 값을 받아와서 buiild
Books books = Books.builder()
.title(bookDTO.getTitle())
.isbn(bookDTO.getIsbn())
.description(bookDTO.getDescription())
.author(bookDTO.getAuthor())
.publisher(bookDTO.getPublisher())
.pubdate(bookDTO.getPubdate())
.build();
// 그 book 값을 board와 book에 함께 저장.
boards.addBook(books);
// 이미지 값을 urlList에서 각각 url로 저장 후 book에도 add
for(String imgUrl : imgUrlList) {
Images image = new Images();
image.setImage_url(imgUrl);
books.addImage(image);
}
// book값을 DB에 저장
bookRepository.save(books);
}
요렇게 해서 실행을 했는데..............
자꾸 null이라는 오류가 난다 ㅠㅡㅠ
널친구는 항상 모때문인지 모르겠어서 어렵다
addBook에서 에러가 났다길래 그 엔터티가서 막 살펴봤지만 연관관계 잘 맺어있고,,,,,,,,
뭐가 문젠지요....?
또 폭풍 서치 그리고 짝꿍 찬스...
짝꿍도 해결 못하고
혼자 또 찾아보다가
알아낸 것..............!!!!!!!!!!!!!!!!!
@Builder가 클래스에 사용될 때 npe가 난다는 것
이유는 build() 과정에서 포함되지 않은 필드들은 모두 null 또는 0이 된다고 한다.
그래서 그럴 때에는 대신 default를 필드에 설정해주어야 한다는 것. (@Builder.Default로!!!)
공식 문서 내용
@Builder.Default
If a certain field/parameter is never set during a build session, then it always gets 0 / null / false. If you've put @Builder on a class (and not a method or constructor) you can instead specify the default directly on the field, and annotate the field with @Builder.Default:
@Builder.Default private final long created = System.currentTimeMillis();
그래서
Boards 엔터티에 Book 맵핑해준 것을 수정.
@Builder.Default
@OneToMany(
mappedBy = "boards",
cascade = CascadeType.ALL,
orphanRemoval = true)
private List<Books> booksList = new ArrayList<>();
그리고 Books 엔터티에 Image 매핑해준 것을 수정.
@Builder.Default
@OneToMany(
mappedBy = "books", // mappedBy는 주인이 아님을 명시
cascade = CascadeType.ALL)
/* cascade옵션은 부모 엔티티에 대한 동작을 자식 엔티티로 전파할 때 사용됨.
모든 영속성 동작(PERSIST, MERGE, REMOVE, REFRESH, DETACH)을 자식 엔티티로 전파하겠다는 의미.
즉 부모엔티티에 대한 변경사항이 자식 엔티티에도 적용된다. */
private List<Images> imagesList = new ArrayList<>();
이렇게 해주니까
같은 builder를 써도 결국은
요렇게 DB에 잘 들어갔다!!!!!!!!!!
예에ㅔㅔㅔㅔㅔㅔㅔ!!!!!
너무 힘겨웠다
1일 1오류 마주하기...ㅎㅎ
많이 배우는 중
'Project > eco reading project' 카테고리의 다른 글
[error] The bucket is in this region: ap-northeast-2 (0) | 2023.11.06 |
---|---|
AWS S3 활용하여 이미지 업로드하기 (Spring) (0) | 2023.11.02 |
new project ! (1) | 2023.11.02 |