public class JpaBaseEntity {
@Column(updatable = false)
private LocalDateTime createdDate;
private LocalDateTime updatedDate;
@PrePersist
public void prePersist() {
LocalDateTime now = LocalDateTime.now();
createdDate = now;
updatedDate = now;
}
}
데이터 입력시간, 수정시간과 같은 컬럼은 사용자가 직접입력하지 않는다.
자동으로 입력하게 만들어두는데 그때 사용하는것이 @PrePersist 어노테이션이다.
PrePersist라는 말과 같이 말그대로 persist하기전에 처리하는 코드이다.
즉 데이터를 넣고 persist를 하려고 할때 @PrePersist 어노테이션이 붙은 prePersist()가
날짜를 now로 기입해주고 persist를 보내는 것이다.
즉 insert하기전에 처리하고 싶은게 있다면 @PrePersist를 사용하는 것이다.
만약 update하기전에 사용하고 싶은게 있다면 @PreUpdate어노테이션을 사용하면 된다.
@PreUpdate
public void preUpdate() {
updatedDate = LocalDateTime.now();
}
✔더티체킹이랑 persist는 다르다.
persist는 말그대로 영속성 컨텍스트에 엔티티를 넣어서 관리하겠다는 것이고
더티체킹은 엔티티를 받아올때 영속성컨텍스트와 스냅샷에 데이터가 담기는데 나중에 영속성컨텍스트의 값이 변하게되면 스냅샷과 달라지고 이때 update를 날리는게 더티체킹이다.
위에는 jpa를 통해 구현한 방식이고 Spring을 통해서도 위의 기능+@createdBy,@LastModifiedBy를 구현할 수 있다.
@EntityListeners(AuditingEntityListener.class)
@MappedSuperclass
@Getter
public class BaseEntity {
@CreatedDate
@Column(updatable = false)
private LocalDateTime createdDate;
@LastModifiedDate
private LocalDateTime lastModifiedDate;
@CreatedBy
@Column(updatable = false)
private String createdBy;
@LastModifiedBy
private String LastModifiedBy;
}
@Entity
@Getter
@Setter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@ToString(of = {"id", "username", "age"})
@NamedQuery(
name="Member.findByUsername",
query="select m from Member m where m.username = :username"
)
@NamedEntityGraph(name="Member.all", attributeNodes = @NamedAttributeNode("team"))
public class Member extends BaseEntity{
@Id
@GeneratedValue
@Column(name = "member_id")
private Long id;
private String username;
private int age;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "team_id")
private Team team;
public Member(String name) {
this.username = name;
}
public Member(String name, int age, Team team) {
this.username = name;
this.age = age;
if (team != null) {
changeTeam(team);
}
}
public Member(String name, int age) {
this.username = name;
this.age = age;
}
public void changeTeam(Team team) {
this.team = team;
team.getMembers().add(this);
}
}
@EnableJpaAuditing
@SpringBootApplication
public class DataJpaApplication {
public static void main(String[] args) {
SpringApplication.run(DataJpaApplication.class, args);
}
@Bean
public AuditorAware<String> auditorProvider() {
return () -> Optional.of(UUID.randomUUID().toString());
}
}
@EntityListeners(AuditingEntityListener.class)을 BaseEntity에
@EnableJpaAuditing 어플리케이션 클래스에 붙여주고
@Bean
public AuditorAware<String> auditorProvider() {
return () -> Optional.of(UUID.randomUUID().toString());
}
해당 빈을 추가해줘야한다.
여기서 한가지 알아야할게 해당 빈의 메소드명은 의미없다. 반환타입이 중요하다.
반환타입이 AuditorAware<String>이여야 하며
해당 반환타입을 오버라이딩 해서 값을 출력한다.
@Bean
public AuditorAware<String> auditorProvider() {
return new AuditorAware<String>() {
@Override
public Optional<String> getCurrentAuditor() {
return Optional.of(UUID.randomUUID().toString());
}
};
// return () -> Optional.of(UUID.randomUUID().toString());
//같은 뜻임 람다로 바꾼것 뿐
}
@EnableJpaAuditing(modifyOnCreate = false)
@SpringBootApplication
public class DataJpaApplication {
public static void main(String[] args) {
SpringApplication.run(DataJpaApplication.class, args);
}
@Bean
public AuditorAware<String> auditorProvider() {
return () -> Optional.of(UUID.randomUUID().toString());
}
}
헤당 코드로 입력하면 처음 엔티티를 create할때 update에 null이 들어간다.
우리가 생각하는 처음에는 입력자만 있지 수정자는 없지않아?의 의미 그대로 적용된다.
하지만 데이터에 null이 들어가게되면 귀찮아 짐으로 보통 맨처음에는 create와 update에 동일한 값을 넣는다.
처음 입력한사람=수정한사람으로 한다.