@entity란 무엇입니까?
JPA로 매핑할 테이블 및 클래스에 첨부되는 주석입니다.
@Entity 주석이 달린 클래스는 JPA에서 관리하는 객체가 됩니다.
주석 임의 사용
@Setter // 문제 1. 객체가 무분별하게 변경될 가능성 있음
@Getter
@NoArgsConstructor // 문제 2. 기본 생성자의 접근 제어자가 불명확함
@AllArgsConstructor // 문제 3. 객체 내부의 인스턴스 멤버들을 모두 가지고 있는 생성자를 생성
@Builder // 문제 4. 모든 매개변수가 생성자 param으로 들어가 객체 생성 시 받지 않아야 할 매개변수도 빌더에 노출
@Data // 문제 5. 사용하지 않는 어노테이션을 따로 exclude 할 수 없기 때문에 개별 어노테이션 사용
@Entity
public class User
문제 1. @Setter
@Setter를 사용하는 경우 객체가 언제든지 수정될 수 있으므로 객체의 안정성을 보장하기 어렵습니다.
특히 Entity에서 @Setter를 사용할 때 변경이 발생한 위치를 추적하기가 어렵습니다.
값의 변경이 필요한 경우 명시적 메서드 생성을 통해 변경하는 것이 좋습니다.
@Getter
@Entity
public class User {
private String email;
private String password;
private String nickname;
public void updateNickname(String nickname) {
this.nickname = nickname;
}
}
용해:@Setter 삭제 후 명시적 메소드 생성
문제 2. @NoArgsConstructor
기본 생성자의 접근 제어(NoArgsConstructor)를 PROTECTED로 설정하면 무분별한 객체 생성 여부를 다시 확인할 수 있습니다.
예를 들어 사용자 클래스에 이메일, 비밀번호, 닉네임 정보가 필요한 경우
기본 생성자를 만들지 않음으로써 불완전한 개체를 만들지 않도록 합니다.
기본 생성자의 권한을 별도로 설정하지 않으면 액세스 수준이 public이 되며 이 경우 다음과 같은 상황이 발생합니다.
// User.java
@Setter
@Getter
@NoArgsConstructor
public class User {
private String email;
private String password;
private String nickname;
}
// Main.java
public static void main(String() args) {
User user = new User();
user.setEmail("[email protected]");
user.setPassword("testpassword1!
!
");
// nickname 이 설정되지 않았기 때문에 user는 완전하지 않은 객체
}
사용자 개체를 생성하고 setter로 값을 설정하면 실수로 필요한 값을 설정하지 않고 개체가 생성됩니다.
그러나 다음과 같이 변경하면 IDE 단계에서 필수 값이 누락되는 것을 방지할 수 있습니다.
// User.java
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class User {
private String email;
private String password;
private String nickname;
public User(String email, String password) {
this.email = email;
this.password = password;
// 파라미터가 두 개인 경우 default 값 설정
this.nickname = "닉네임을 설정하세요";
}
}
// Main.java
public static void main(String() args) {
User user = new User(15, "[email protected]");
// 기본 생성자가 없고 객체가 지정한 생성자를 사용해야하기 때문에
// 무조건 완전한 상태의 객체가 생성되게 된다.
}
용해:@NoArgsConstructor(접속 = AccessLevel.PROTECTED)로 변경
문제 3. @AllConstructor
@AllConstructor는 클래스에 존재하는 모든 필드에 대한 생성자를 자동으로 생성합니다.
인스턴스 멤버 변수의 순서를 변경하면 입력 값의 순서도 변경되어 감지되지 않은 치명적인 오류가 발생할 수 있으므로 @AllConstructor를 사용하지 않는 것이 좋습니다.
용해:@AllConstructor 제거
작업 4. @Builder
클래스 레벨에서 @Builder와 @NoArgsConstructor를 함께 컴파일하면 오류가 발생합니다.
이것은 @AllArgsConstructor를 추가하여 해결할 수 있습니다.
그러나 위의 3번 문제에서 언급했듯이 AllArgsConstructor를 사용하지 않는 것이 좋습니다.
따라서 생성자에 @Builder를 선언하면 빌더에 객체를 생성할 때 받아서는 안 되는 매개변수를 노출시키는 문제를 해결할 수 있다.
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class User {
private String email;
private String password;
private String nickname;
@Builder
public User(String email, String password) {
this.email = email;
this.password = password;
this.nickname = "닉네임을 설정하세요";
}
@Builder
public User(String email, String password, String nickname) {
this.email = email;
this.password = password;
this.nickname = nickname;
}
}
용해:클래스에서 @Builder를 삭제하고 생성자에 @Builder를 추가합니다
작업 5. @data
@데이터는 @Getter입니다.
, @세터, @RequiredArgs 생성자, @ToString, @EqualsAndHashCode모든 것을 한 번에 수정하는 주석입니다.
@Data에 포함된 롬복 설정(예: callSuper, includeFieldNames, Exclude)를 지정할 수 없으며 사용하지 않는 주석도 즉시 선언됩니다.
따라서 @Data 주석을 사용하지 않고 필요한 개별 주석을 추가하는 것이 좋습니다.
용해:필요한 주석을 모두 추가하세요
용도
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Entity
public class Member {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String email;
private String password;
private String nickname;
public void updateNickname(String nickname) {
this.nickname = nickname;
}
@Builder
public User(String email, String password) {
this.email = email;
this.password = password;
this.nickname = "닉네임을 설정하세요";
}
@Builder
public User(String email, String password, String nickname) {
this.email = email;
this.password = password;
this.nickname = nickname;
}
}
https://velog.io/@cieroyou/Builder-%EC%82%AC%EC%9A%A9%EB%B2%95