JPA Auditing (@MappedSuperclass의 사용 )

김건우·2022년 12월 4일
0

Spring Data JPA

목록 보기
5/11
post-thumbnail

@MappedSuperClass

  • 객체의 입장에서 공통 매핑정보가 필요할 때 사용한다.

  • 공통 매핑 정보가 필요할 때 ,부모 클래스에 선언을 해주고 속성만 상속 받아서 사용하고 싶을 때 @MappedSuperClass 를 사용한다. 상속광계 매핑이 아니다.

  • @MappedSuperclass가 선언되어 있는 클래스는 엔티티가 아니다. 당연히 테이블과 매핑도 안된다. 단순히 부모 클래스를 상속 받는 자식 클래스에 매핑 정보만 제공한다.

  • 조회, 검색이 불가하다. 부모 타입으로 조회하는 것이 불가능하다는 이야기.(em.find(BaseEntity) 불가능)

  • 직접 생성해서 사용할 일이 없으므로 추상 클래스로 만드는 것을 권장한다.

  • 테이블과 관계가 없고, 단순히 엔티티가 공통으로 사용하는 매핑 정보를 모으는 역할을 한다.

  • 주로 등록일, 수정일, 등록자, 수정자 같은 전체 엔티티에서 공통으로 적용하는 정보를 모을 때 사용한다.

@PrePersist

:JPA 엔티티(Entity)가 비영속(new/transient) 상태에서 영속(managed) 상태가 되는 시점 이전에 실행되는 어노테이션

@PreUpdate

:영속 상태의 엔티티를 이용하여 데이터 업데이트를 수행하기 이전에 실행되는 어노테이션

다음은 순수 JPA를 사용해서 공통 매핑정보의 컬럼들을 @MapperSuperClass를 사용한 클래스의 코드이다.

@MappedSuperclass
@Getter
public class JpaBaseEntity {
 @Column(updatable = false)
 private LocalDateTime createdDate;
 private LocalDateTime updatedDate;
 @PrePersist
 public void prePersist() {
 LocalDateTime now = LocalDateTime.now();
 createdDate = now;
 updatedDate = now;
 }
 @PreUpdate
 public void preUpdate() {
 updatedDate = LocalDateTime.now();
 }
}

밑의 Member엔티티는 @MappedSuperclass의 클래스인 BaseEntity를 상속 받는다

@Entity
public class Member extends BaseEntity {
  ...
}

해당 SQL을 보면 member 엔티티를 create할 때 BaseEntity의 컬럼들 마저 생성된것을 볼 수 있다.
Hibernate:
create table Member (
id bigint generated by default as identity,
createdBy varchar(255),
createdDate timestamp,
lastModifiedBy varchar(255),
lastModifiedDate timestamp,
age integer,
name varchar(255),
team_id bigint,
primary key (id)
)

이제 Spring data JPA가 제공하는 Auditing 기능을 사용해보겠다!

  1. 최우선적으로 스프링부트 설정클래스에 제일 먼저 @EnableJpaAuditing 어노테이션을 붙여줘야 한다.
@EnableJpaAuditing
@SpringBootApplication
public class GunshopApplication {

    public static void main(String[] args) {
        SpringApplication.run(GunshopApplication.class, args);
    }

}

이렇게 스프링부트 Main메서드가 있는 클래스에 @EnableJpaAuditing를 붙여주자

  1. @MappedSuperclass의 기능을 사용할 BaseEntity라는 클래스를 제작해주자. 순수 JPA를 사용한 JpaBaseEntity클래스보다 코드가 훨씬 준것을 알 수 있다. @Persist , @PreUpdate를 메소드로 만들어서 쓰는 대신 컬럼위에 @CreatedDate , @LastModifiedDate 어노테이션을 각각 컬럼에 붙여주자. 그리고 또한 해당 BaseEntity 클래스에 @EntityListeners(AuditingEntityListener.class)를 써주는 것을 잊지말자.해당 클래스에 Auditing 기능을 포함한다는 어노테이션이다.
@EntityListeners(AuditingEntityListener.class)
@MappedSuperclass @Getter
public class BaseEntity {

    @CreatedDate
    @Column(updatable = false) // 생성시간은 update되면 안됨
    private LocalDateTime createDate;

    @LastModifiedDate
    private LocalDateTime lastModifiedDate;
}

다음 아래의 코드는 BaseEntity를 상속받은 Member엔티티이다.

@Entity
@Getter @Setter @AllArgsConstructor
public class Member extends BaseEntity{

    /**
     * 회원은 여러 상품을 주문할 수 있다
     */
    @Id
    @GeneratedValue
    @Column(name = "member_id")
    private Long id;

    private String loginId;

    private String password;

    private String name;

    @Embedded
    private Address address;

    @OneToMany(mappedBy = "member")
    private List<Order> orders = new ArrayList<>();

이제 어플리케이션을 실햏해보면
Member엔티티에 해당 컬럼을 직접 안써주어도 테이블을 Create할때 해당 컬럼이 생성되는것을 볼 수 있다. 쿼리문과 테이블 🔽

  • @MappedBySupperClass를 상속받은 Member엔티티 생성 Create SQL
  • 실제 회원 객테 생성시 생성되는 CREATE_DATE 와 LAST_MODIFIED_DATE
profile
Live the moment for the moment.

0개의 댓글