https://github.com/mizm/board-toy
위의 레포지토리에 저장해두었습니다.
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.domain.AuditorAware;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
import java.util.Optional;
import java.util.UUID;
@EnableJpaAuditing
@Configuration
public class JpaConfig {
@Bean
public AuditorAware<String> auditorProvider() {
//security를 통해 유저아이디를 꺼내오자.
return () -> Optional.of(UUID.randomUUID().toString());
}
}
import lombok.Getter;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import javax.persistence.Column;
import javax.persistence.EntityListeners;
import javax.persistence.MappedSuperclass;
import java.time.LocalDateTime;
@EntityListeners(AuditingEntityListener.class)
@MappedSuperclass
@Getter
public class BaseTimeEntity {
@CreatedDate
@Column(updatable = false, name = "created_date")
private LocalDateTime createdDate;
@LastModifiedDate
@Column(name = "modified_date")
private LocalDateTime modifiedDate;
}
import lombok.Getter;
import org.springframework.data.annotation.CreatedBy;
import org.springframework.data.annotation.LastModifiedBy;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import javax.persistence.Column;
import javax.persistence.EntityListeners;
import javax.persistence.MappedSuperclass;
@EntityListeners(AuditingEntityListener.class)
@MappedSuperclass
@Getter
public class BaseEntity extends BaseTimeEntity {
@CreatedBy
@Column(updatable = false, name = "created_by")
private String createdBy;
@LastModifiedBy
@Column(name = "updated_by")
private String updatedBy;
}
@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class User extends BaseTimeEntity{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "user_id")
private Long id;
@Column(length = 50)
private String username;
private String password;
private String email;
@Builder
public User(String username, String password, String email) {
Assert.hasText(username, "username is Not null");
Assert.hasText(password, "password is Not null");
Assert.hasText(email, "email is Not null");
this.username = username;
this.password = password;
this.email = email;
}
}
@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Board extends BaseEntity{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "board_id")
private Long id;
private String title;
@Column(columnDefinition = "TEXT")
private String content;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user_id")
private User user;
@Builder
public Board(String title, String content, User user) {
Assert.hasText(title, "title is not null");
Assert.hasText(content, "content is not null");
Assert.notNull(user, "user is not null");
this.title = title;
this.content = content;
this.user = user;
}
}
@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Comment extends BaseEntity{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "comment_id")
private Long id;
@Column(length = 500)
private String content;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user_id")
private User user;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "board_id")
private Board board;
@Builder
public Comment(String content, User user, Board board) {
Assert.hasText(content, "title is not null");
Assert.notNull(user, "user is not null");
Assert.notNull(board, "board is not null");
this.content = content;
this.user = user;
this.board = board;
}
}
@NoArgsConstructor(access = AccessLevel.PROTECTED) -> Spring 에서 Proxy를 만들때 아무것도 없는 생성자가 필요함
- 혹시라도 모르니 access를 protected로 지정한다.
- ex) User 클래스 기준으로 아래의 코드가 Lombok을 통해 생성 된다.
```java
protected User() {
}
```
모든 ManyToOne 관계는 fetchType을 Lazy로딩으로 지정해준다
- N+1 문제 해결을 위해
기본적인 연관관계매핑은 FK가 들어가는 Entity에만 지정 해둔뒤 추후 필요에 따라 구현
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import spring.board.entity.User;
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
}
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import spring.board.entity.Board;
@Repository
public interface BoardRepository extends JpaRepository<Board, Long> {
}
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import spring.board.entity.Comment;
@Repository
public interface CommentRepository extends JpaRepository<Comment, Long> {
}