Entity Annotation
import lombok.*;
import javax.persistence.*;
import java.util.*;
@Getter
@ToString(callSuper = true)
@Table(indexes = {
@Index(columnList = "title"),
})
@EntityListeners(AuditingEntityListener.class)
@Entity
public class Article {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Setter
@ManyToOne(optional = false)
@JoinColumn(name = "user_id")
private User user; // 유저 정보(ID)
@Setter
@Column(nullable = false)
private String title; // 제목
@Setter
@Column(nullable = false, columnDefinition = "TEXT")
private String content; // 본문
@Setter
private String hashtag; // 해시태그
// mappedBy 를 걸지 않으면 두 entity 이름을 합쳐서 테이블을 하나 만듬
@ToString.Exclude
@OrderBy("createdAt DESC")
@OneToMany(mappedBy = "article", cascade = CascadeType.ALL)
private final Set<ArticleComment> articleComments = new LinkedHashSet<>();
@CreateDate @Column(nullable = false) private LocalTime createdTime;
@CreateBy @Column(nullable = false, length = 100) private String createdBy;
@LastModifiedDate @Column(nullable = false) private LocalTime updatedTime;
@LastModifiedBy @Column(nullable = false, length = 100) private String updatedBy;
// public, protected no-arg constructor -> entity
protected Article() {
}
private Article(User user, String title, String content, String hashtag) {
this.user = user;
this.title = title;
this.content = content;
this.hashtag = hashtag;
}
// factory method
public static Article of(User user, String title, String content, String hashtag) {
return new Article(user, title, content, hashtag);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
// Pattern Matching for instanceof in Java 14
if (!(o instanceof Article article)) return false;
return id != null && id.equals(article.id);
}
@Override
public int hashCode() {
return Objects.hash(id);
}
}
@ToString
: [effective java item 12] toString을 항상 재정의하라System.out.println(article)
와 같이 작성하면 내부 내용을 볼 수 있으므로 디버깅하기 쉽다.toString()
을 재정의하면 모든 값을 알아내기에 매우 좋다.callSuper = true (default: false)
: 출력에 슈퍼클래스의 toString 구현 결과를 포함합니다.@ToString.Exclude
: 연관 관계에 있는 필드에는 exclude annotation을 통해 toString을 제외시킨다. 이는 순환 toString이 발생하면 무한한 메서드 콜이 발생한다.// mappedBy 를 걸지 않으면 두 entity 이름을 합쳐서 테이블을 하나 만듬
@ToString.Exclude
@OrderBy("createdAt DESC")
@OneToMany(mappedBy = "article", cascade = CascadeType.ALL)
private final Set<ArticleComment> articleComments = new LinkedHashSet<>();
@OneToMany(mappedBy = "article", cascade = CascadeType.ALL)
OrderBy("createdAt desc")
: Collection의 조회 순서를 정할 수 있다. 이는 JPA 쿼리를 작성할 때 유용하다.Example 1:
@Entity
public class Course {
...
@ManyToMany
@OrderBy("lastname ASC")
public List<Student> getStudents() {...};
...
}
Example 2:
@Entity
public class Student {
...
@ManyToMany(mappedBy="students")
@OrderBy // ordering by primary key is assumed
public List<Course> getCourses() {...};
...
}
Example 3:
@Entity
public class Person {
...
@ElementCollection
@OrderBy("zipcode.zip, zipcode.plusFour")
public Set<Address> getResidences() {...};
...
}
@Embeddable
public class Address {
protected String street;
protected String city;
protected String state;
@Embedded protected Zipcode zipcode;
}
@Embeddable
public class Zipcode {
protected String zip;
protected String plusFour;
}
// public, protected no-arg constructor -> entity
protected Article() {
}
(필자는 필드 값을 주입하기 위한 것 같다.)
@Override
public boolean equals(Object o) {
if (this == o) return true;
// Pattern Matching for instanceof in Java 14
if (!(o instanceof Article article)) return false;
return id != null && id.equals(article.id);
}
@Override
public int hashCode() {
return Objects.hash(id);
}
@EnableJpaAuditing
@SpringBootApplication
public class BoardToyProjectApplication {
public static void main(String[] args) {
SpringApplication.run(BoardToyProjectApplication.class, args);
}
}
@EntityListeners(AuditingEntityListener.class)
@Entity
public class Article {
@CreateDate @Column(nullable = false) private LocalTime createdTime;
@CreateBy @Column(nullable = false, length = 100) private String createdBy;
@LastModifiedDate @Column(nullable = false) private LocalTime updatedTime;
@LastModifiedBy @Column(nullable = false, length = 100) private String updatedBy;
}
@Getter
@ToString
@EntityListeners(AuditingEntityListener.class)
@MappedSuperclass
public abstract class AuditingFields {
// 상식적으로 Jpa Auditing 은 not null
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
@CreatedDate
@Column(nullable = false, updatable = false)
private LocalDateTime createdAt; // 생성일시
@CreatedBy
@Column(nullable = false, updatable = false, length = 100)
private String createdBy; // 생성자
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
@LastModifiedDate
@Column(nullable = false)
private LocalDateTime modifiedAt; // 수정일시
@LastModifiedBy
@Column(nullable = false)
private String modifiedBy; // 수정자
}
@Getter
@ToString(callSuper = true)
@Table(indexes = {
@Index(columnList = "title"),
@Index(columnList = "hashtag"),
@Index(columnList = "createdAt"),
@Index(columnList = "createdBy")
})
@Entity
public class Article extends AuditingFields {
...
}