그 주의 화요일, 금요일을 지정 날짜로 업데이트 합니다
일급 컬렉션을 통해 Java 단일 객체로 맵핑을 시켜주려했을시 오류가 발생하였다.
@OneToMany(mappedBy = "user", cascade = CascadeType.ALL)
private Answers answer;
@ManyToOne, @OneToMany, @CollectionOfElements annotation 의 경우 non Collection 객체와는 매핑될 수 없다.
(일급 컬렉션의 선언된 부분에 들어가서 맵핑을 해줘야 오류가 발생하지 않는다.)
@OneToMany(mappedBy = "user", cascade = CascadeType.ALL)
private List<Answer> answer = new ArrayList<>();
발생한 에러 메시지
AnnotationException: Illegal attempt to map a non collection as a @OneToMany, @ManyToMany or @CollectionOfElements
JPA의 엔티티 타입은 기본값, 임베디드, 컬렉션 타입으로 나눌 수 있다.
이때 임베디드 타입(Embedded Type)은 JPA에서 사용자가 직접 정의한 값 타입이다.
임베디드 타입 사용할 때의 장점
엔티티가 상세한 데이터를 그대로 가지고 있는 것은 응집력을 떨어트리고 객체지향적이지 않다.
때문에 유사한 상세한 데이터들을 묶어서 새로 정의한 값 타입으로 사용할 수 있고, 임베디드 타입을 사용함으로써 새로 정의한 값 타입들을 재사용할 수 있으며 엔티티의 응집도를 높일 수 있다. 다만, 공유 참조로 인해 버그가 발생할 수 있으므로 불변 객체로 설계해야한다.
또한, 임베디드 타입 덕분에 객체와 테이블을 세밀하게 매핑할 수 있다.
(잘 설계한 ORM 애플리케이션은 테이블 컬럼과 객체 필드가 1:1로 매핑되는 것이 아니라 매핑한 테이블의 수보다 클래스의 수가 더 많아지게 된다.)
@Entity
public class Member {
@Id @GeneratedValue
private Long id;
@Column(name="name")
private String name;
@Embedded
private Address address;
}
@Embeddable
public class Address {
private String country;
private String city;
}
객체 지향의 이상적인 설계 "응집도는 높이고, 결합도는 낮춰야한다"
핵심은 객체 설계시 객체가 여러 기능을 모두 한번에 짊어지게 하는 것보다 객체 고유의 기능이 무엇인지 생각해보는 것이다. 객체의
역할
과책임
을 맞게 잘 분배하였는지를 생각하면 된다. 또한 결합에 있어서는 객체간협력
에 필요한 적절한 수준의 관계만을 유지하는 것이 중요하다.
IllegalArgumentException
대신 NullPointerException
Throw)toString
등을 통해 예외 발생에 영향을 준 모든 필드와 인자의 값이 들어 있어야 한다. 이를 통해 예외를 메시지를 보고 실패 원인을 알 수 있어야한다.e.printStackTrace()
보다는 로깅 프레임워크를 사용하는 편이 좋다.예외처리에 대한 리팩터링을 진행하면서 받은 피드백
- 실패에 대한 자세한 정보를 상세 메시지에 담아야한다.
회원에 대한 정보를 업데이트 하고자 할 때, 회원 아이디가 맞지 않으면 예외를 발생시키는 코드를 구현하였다. 하지만 다음과 같은 코드에서는 Exception에는 실패에 대한 메시지가 부족한 문제점이 있다. Exception과 관련하여 충분한 메시지를 남겨야 추후에 트래킹이 가능할 수 있다.public void update(UserInfo loginUser, UserInfo target) { if (!matchUserId(loginUser.userId)) { throw new UnAuthorizedException("사용자가 일치하지 않습니다."); //throw new UnAuthorizedException(); } /... this.name = name; }
- 추상화 수준에 맞는 예외를 던져라
모든 예외를 상위로 던지기보다는 추상화 수준에 맞는 예외로 바꿔서(예외번역) 던져야 한다.public void validateDelete(User loginUser) throws CannotDeleteException { for (Answer answer : answers) { answer.validateDelete(loginUser); } }
추상화 수준에 맞는 예외로 던진다는 것은 무슨 의미일까?
의미 있는 예외로 변환하여 던지는 것을 생각하면 될 것 같다.
메서드가 저수준 예외를 처리하지 않고 바깥으로 전파(throws) 하는 경우 수행하려는 일과 관련없는 예외가 발생할 수 있기 때문이다.public void validateDelete(User loginUser) throws Exception { try { for (Answer answer : answers) { answer.validateDelete(loginUser); } } catch (CannotDeleteException e) { throw new Exception(""); } }
[참조]
https://codingexplore.tistory.com/74
JPA 프로그래밍
https://github.com/mgp/book-notes/blob/master/effective-java-2nd-edition.markdown#chapter-9-exceptions
https://www.slipp.net/questions/350
https://jjingho.tistory.com/124
https://github.com/Meet-Coder-Study/book-effective-java/blob/main/10%EC%9E%A5/73_%EC%B6%94%EC%83%81%ED%99%94_%EC%88%98%EC%A4%80%EC%97%90_%EB%A7%9E%EB%8A%94_%EC%98%88%EC%99%B8%EB%A5%BC_%EB%8D%98%EC%A0%B8%EB%9D%BC_%EB%B0%95%EC%86%8C%EC%A0%95.md