-
Notifications
You must be signed in to change notification settings - Fork 0
JPA Create And Update Value
정명주(myeongju.jung) edited this page Aug 5, 2018
·
6 revisions
- 도메인에서 핵심 관심사를 관통하는 용도로 상속이라는 귀중한 기회를 사용해야한다고 봄.
- 하지만 팀의 합의가 있다면 구현 편의를 위해서 상속을 사용하는 것도 하나의 방법임.
- 개인적으로는 권장하지 않음
- 하지만 대중적으로 가장 많이 쓰이고 있고 개발 시 편함
@Getter
@ToString
@EqualsAndHashCode
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
class BaseEntity {
@CreatedBy
private Long createdUserId
@CreatedDate
private Date createdAt;
@LastModifiedBy
private Long lastModifiedUserId
@LastModifiedDate
private Date lastModified;
}
@Configuration
@EnableJpaAuditing // 이 설정이 있어야지 위 어노테이션이 정상작동
class JpaConfig {
@Bean
public AuditorAware<AuditableUser> auditorProvider() {
return new MyAuditorAware(); // 사용자 조회 용
}
}
- 등록과 수정정보과 통합된 형태의 값객체
@Embeddable
@Getter
@ToString
@EqualsAndHashCode
@AllArgsConstructor
public class CreateAndUpdate {
public static final String CN_CREATE_USER_NO = "CREATE_USER_NO";
public static final String CN_CREATED_AT = "CREATED_AT";
public static final String CN_UPDATE_USER_NO = "UPDATE_USER_NO";
public static final String CN_UPDATED_AT = "UPDATED_AT";
public static final String DB_CURRENT_TIMESTAMP = "CURRENT_TIMESTAMP";
/**
* 등록 회원번호
*/
@Column(name = CN_CREATE_USER_NO, nullable = false, updatable = false)
private final Long createUserNo;
/**
* 등록일시
*/
@ColumnDefault(DB_CURRENT_TIMESTAMP)
@Generated(GenerationTime.INSERT)
@Temporal(TemporalType.TIMESTAMP)
@Column(name = CN_CREATED_AT, nullable = false, insertable = false, updatable = false)
private final Date createdAt;
/**
* 수정 회원번호
*/
@Column(name = CN_UPDATE_USER_NO, insertable = false)
private Long updateUserNo;
/**
* 수정일시
*/
@Temporal(TemporalType.TIMESTAMP)
@Column(name = CN_UPDATED_AT, insertable = false)
private Date updatedAt;
protected CreateAndUpdate() {
this.createUserNo = null;
this.createdAt = null;
}
private CreateAndUpdate(Long createUserNo) {
this.createUserNo = createUserNo;
this.createdAt = null;
this.updateUserNo = null;
this.updatedAt = null;
}
public static CreateAndUpdate create(@NonNull Long createUserNo) {
return new CreateAndUpdate(createUserNo);
}
public void update(@NonNull Long updateUserNo) {
this.updateUserNo = updateUserNo;
this.updatedAt = new Date();
}
public void checkPreInsert() {
if (createUserNo == null) {
throw new IllegalStateException("'createUserNo' not exist when create");
}
}
public void checkPreUpdate() {
if (createUserNo == null) {
throw new IllegalStateException("'createUserNo' not exist when update");
}
if (updateUserNo == null) {
throw new IllegalStateException("'updateUserNo' not exist when update");
}
}
}
- 등록과 수정정보과 분리된 형태의 값객체
Storeable
public interface Storeable {
String getMemberId();
ZonedDateTime getTs();
}
Register
@Value
@Embeddable
@AllArgsConstructor
public class Register implements Storeable, Serializable {
private static final long serialVersionUID = 6901279822511498217L;
@Column(name = "register_member_id", length = 100, nullable = false, updatable = false)
private final String memberId;
@Generated(GenerationTime.INSERT)
@ColumnDefault(DB_CURRENT_TIMESTAMP)
@Column(name = "register_ts", nullable = false, insertable = false, updatable = false)
private final ZonedDateTime ts;
// for JPA
protected Register() {
this.memberId = null;
this.ts = null;
}
public static Register create(String registerMemberId) {
if (StringUtils.isBlank(registerMemberId)) {
throw new IllegalArgumentException("'registerMemberId' is blank");
}
return new Register(registerMemberId, ZonedDateTime.now());
}
public boolean isEmpty() {
return memberId == null && ts == null;
}
}
Modify
@Value
@Embeddable
@AllArgsConstructor
public class Modify implements Storeable, Serializable {
public static final String DB_CURRENT_TIMESTAMP = "CURRENT_TIMESTAMP";
private static final long serialVersionUID = -1206032844696773181L;
@Column(name = "modify_member_id", length = 100, nullable = false)
private String memberId;
// @Generated(GenerationTime.INSERT) // 이 부분은 고민 중
@ColumnDefault(DB_CURRENT_TIMESTAMP)
@Column(name = "modify_ts", insertable = false, nullable = false)
private ZonedDateTime ts;
// for JPA
protected Modify() {
this.memberId = null;
this.ts = null;
}
public static Modify create(String modifyMemberId) {
if (StringUtils.isBlank(modifyMemberId)) {
throw new IllegalArgumentException("'modifyMemberId' is blank");
}
return new Modify(modifyMemberId, ZonedDateTime.now());
}
}
JAVA
JPA
- JPA-Create-And-Update
- Optional-Eager
- QueryDsl-Configuration
- QueryDsl-More-Type-safety
- QueryDsl-SubQuery
DDD
Install
Spring
Spring-Boot
- Swagger2-Configuration
- Spring-Restdocs-Configuration
- Spring-Page-Jackson
- JSR310-Guide
- logback-spring.xml
- WebMvcUtils.java
- Spring-Boot-Properties
- Spring-Boot-Hidden-Gems
- Spring-Boot-Config
Spring-Cloud
- Spring-Cloud-Zuul
- Spring-Cloud-Feign
- Spring-Cloud-Hystrix
- Spring-Cloud-Consul
- Spring-Cloud-Ribbon
- Spring-Cloud-Circuit-Breaker
JavaScript
Gradle
Test
Linux
Etc
TODO http://zoltanaltfatter.com/2017/06/09/publishing-domain-events-from-aggregate-roots/