728x90
시스템이 매우 큰 경우 또는 어떤 이유로든 Entity의 @Id를 직접 지정해야하는 경우가 있습니다.
이럴 때에는 아래와 같이 Persistable의 isNew를 override 해주어야 합니다. isNew 판단 여부는 Audit의 기능을 사용했습니다.
@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Member extends BaseEntity implements Persistable<Long> {
@Id
@Column(name = "member_id")
private String id;
@Override
public boolean isNew() {
return super.getCreatedDate() == null;
}
@EntityListeners(AuditingEntityListener.class)
@MappedSuperclass
@Getter
public abstract class BaseEntity {
@CreatedBy
private String createdBy;
@LastModifiedBy
private String lastModifiedBy;
// 필요한 경우 BaseTimeEntity로 분리하기
@CreatedDate
@Column(updatable = false)
private LocalDateTime createdDate;
@LastModifiedDate
@Column(updatable = false)
private LocalDateTime lastModifiedDate;
}
@EnableJpaAuditing
@SpringBootApplication
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
@Bean
public AuditorAware<String> auditorProvider(){
// spring security
return () -> Optional.of(UUID.randomUUID().toString());
}
}
Persistable의 isNew를 override 해주지 않으면 SimpleJpaRepository의 save를 호출할 때 새로운 객체로 인식되지 않아 merge가 호출됩니다. merge는 수행과정에서 select 쿼리를 한 번 호출하기 때문에 persist보다 비효율적입니다.
@Transactional
@Override
public <S extends T> S save(S entity) {
Assert.notNull(entity, "Entity must not be null.");
if (entityInformation.isNew(entity)) {
em.persist(entity);
return entity;
} else {
return em.merge(entity);
}
}
이러한 방법을 쓰기 전에 정말로 @GeneratedValue(strategy = GenerationType.AUTO)를 사용하지 않아야하는 이유가 있는지는 고민해보아야 합니다.
728x90
'DEV > Spring Data JPA' 카테고리의 다른 글
데이터베이스 트랜잭션 기초 (0) | 2024.03.18 |
---|---|
Open Session In View (1) | 2024.03.18 |
JpaRepository를 custom해서 사용하는 방법 (0) | 2023.09.24 |
QueryHint를 적용하기 전에 고려해볼 사항 (0) | 2023.09.24 |
@EntityGraph로 fetch join 쉽게 쓰기 (0) | 2023.09.24 |