공식문서에 Spring Data JDBC에서 객체를 생성하는 알고리즘을 다음과 같이 설명하고있다.
- If the property is immutable but exposes a with… method (see below), we use the with… method to create a new entity instance with the new property value.
- If property access (i.e. access through getters and setters) is defined, we’re invoking the setter method.
- If the property is mutable we set the field directly.
- If the property is immutable we’re using the constructor to be used by persistence operations (see Object creation) to create a copy of the instance.
- By default, we set the field value directly.
4번에 따르면 wither가 없어도 all-arguments 생성자를 통해서 create 되야 하는 게 아닌가?
General recommendations에도
For identifiers to be generated, still use a final field in combination with an all-arguments persistence constructor (preferred) or a with… method —
또는 with... 메소드인데 왜 all-arguments counstructor 만으로 안될까?
몇 시간에 걸쳐 이런저런 실험을 해봤지만 답을 찾을 수 없었다.🤔
---2020.10.03
다섯 달이 지났는데 아직도 안될까해서 다시 해보니까 된다. 저 글을 쓸 당시에는 정말 안됐었는데 그때 실험했던 코드를 올려놨었으면 같은 코드로 실험을 했을텐데 아쉽다.
저 때도 꽤 오랜시간 삽질을 했으니 안됐었던 건 확실하다. 무튼 지금은 공식 문서 내용대로 wither 메서드 없이 all argument constructor 만으로 불변 엔티티를 잘 사용할 수 있다!
public class Article {
@Id
private final Long id;
private final String title;
private final String content;
private final Set<Comment> comments;
public static Article of(String title, String content, Set<Comment> comments) {
return new Article(null, title, content, comments);
}
Article(Long id, String title, String content, Set<Comment> comments) {
this.id = id;
this.title = title;
this.content = content;
this.comments = comments;
}
public void addComment(Comment comment) {
this.comments.add(comment);
}
public Long getId() {
return id;
}
}
public class Comment {
@Id
private final Long id;
private final String content;
public static Comment of(String content) {
return new Comment(null, content);
}
Comment(Long id, String content) {
this.id = id;
this.content = content;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Comment comment = (Comment) o;
return Objects.equals(id, comment.id);
}
@Override
public int hashCode() {
return Objects.hash(id);
}
}
public interface ArticleRepository extends CrudRepository<Article, Long> {
@Override
List<Article> findAll();
}
@DataJdbcTest
class ArticleRepositoryTest {
@Autowired
ArticleRepository articleRepository;
@DisplayName("create")
@Test
void create() {
Article article = Article.of("title", "content", new HashSet<>());
article.addComment(Comment.of("1"));
Article save = articleRepository.save(article);
Article find = articleRepository.findById(save.getId()).get();
assertThat(find).isEqualToComparingFieldByField(save);
}
}
'삽질' 카테고리의 다른 글
Spring Data Jpa의 LazyInitializationException과 OSIV (0) | 2020.09.09 |
---|---|
Reflection API와 JPA, Spring Bean (0) | 2020.07.22 |
JPA, EntityManager와 persist 관련 알게 된 사실 (0) | 2020.07.15 |
Wrapper Class, Primitive Type == 비교와 NPE 및 HashSet 관련 삽질 (2) | 2020.07.01 |
RestAssured와 기본 생성자에 관련된 삽질 (0) | 2020.05.20 |