본문 바로가기
JAVA/JPA

JPA에서 @Transient 어노테이션 활용하기: 데이터베이스와 관련 없는 정보 다루기

by GangDev 2024. 3. 29.

 

@Transient 어노테이션은 JPA에서 사용되며, 해당 어노테이션을 필드에 적용하면 해당 필드가 엔티티의 일부가 아니며, 데이터베이스와 매핑되지 않아야 함을 나타낸다.
이 어노테이션은 주로 엔티티 클래스 내에서 임시적인 정보나 계산된 값을 저장할 때 사용된다.
이를 통해 데이터베이스와 관련 없는 엔티티 내의 부가 정보를 효과적으로 다룰 수 있다.

 

엔티티 클래스와 데이터베이스 매핑:
일반적으로 JPA를 사용하여 엔티티 클래스를 정의할 때, 엔티티 클래스의 필드들은 데이터베이스의 컬럼과 매핑된다.
이렇게 매핑된 필드들은 데이터베이스 테이블에 저장되거나 조회되는 역할을 한다.

 

@Transient 어노테이션 사용:
그러나 때로는 엔티티 클래스 내에 데이터베이스에 저장하지 않아도 되는 정보나 계산된 값이 필요할 수 있다.
이런 경우, @Transient 어노테이션을 해당 필드에 적용하여 데이터베이스와의 매핑을 방지한다.
예를 들어, 주문 엔티티 클래스에서 주문 총액을 계산하여 저장하지 않고 매번 필요할 때 계산하여 사용할 수 있다.
이때 총액 필드를 @Transient로 표시하면 데이터베이스에 저장되지 않는다.

 

계산된 값 및 임시 정보 저장:
@Transient 어노테이션을 사용하여 저장하지 않는 필드는 주로 계산된 값이나 임시적인 정보를 저장하는 데 활용된다.
이러한 필드는 영속성 컨텍스트에서 관리되지 않으며, 데이터베이스와 관련이 없는 엔티티 내의 부가적인 정보를 담을 때 유용하다.

 

주의:
@Transient 어노테이션이 적용된 필드는 데이터베이스와 관련이 없기 때문에, 해당 필드에 대한 데이터베이스 조회나 저장은 이루어지지 않는다.
@Transient 어노테이션을 사용할 때는 엔티티 클래스 내에서 해당 필드를 사용할 때 주의해야 한다. 이 필드는 엔티티의 생명주기 동안 데이터베이스에 저장되지 않으므로, 필요한 경우에는 코드 내에서 명시적으로 계산하거나 설정해주어야 한다.

@Entity
@Table(name = "orders")
public class Order {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    // 다수의 주문 아이템을 관리하는 컬렉션
    @OneToMany(mappedBy = "order", cascade = CascadeType.ALL)
    private List<OrderItem> orderItems = new ArrayList<>();

    // 주문 총액 - 데이터베이스와 매핑하지 않음
    @Transient
    private BigDecimal totalAmount;

    // 생성자, 게터, 세터 등 필수 코드는 생략
}

 

위 코드에서 totalAmount 필드는 주문 총액을 나타내는데, 이 필드에 @Transient 어노테이션을 사용하여 데이터베이스와의 매핑을 하지 않았다.
이는 주문 총액을 매번 필요할 때마다 계산하고자 하는 경우에 유용하다.
이제 주문 아이템(OrderItem) 엔티티 클래스를 살펴보면,

@Entity
@Table(name = "order_items")
public class OrderItem {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    // 주문 아이템의 가격
    @Column(name = "price")
    private BigDecimal price;

    // 주문 아이템의 수량
    @Column(name = "quantity")
    private int quantity;

    // 주문과의 관계 설정
    @ManyToOne
    @JoinColumn(name = "order_id")
    private Order order;

    // 생성자, 게터, 세터 등 필수 코드는 생략
}

 

여기서는 OrderItem 엔티티 클래스가 주문 아이템의 가격(price)과 수량(quantity)을 저장한다.
이러한 주문 아이템들은 주문(Order) 엔티티와 관련이 있으며, @ManyToOne 어노테이션과 @JoinColumn 어노테이션을 사용하여 관계를 설정한다.

 

이제 주문 총액을 계산하는 메소드를 Order 엔티티 클래스에 추가해보면,

public BigDecimal calculateTotalAmount() {
    totalAmount = BigDecimal.ZERO;
    for (OrderItem item : orderItems) {
        BigDecimal itemTotal = item.getPrice().multiply(BigDecimal.valueOf(item.getQuantity()));
        totalAmount = totalAmount.add(itemTotal);
    }
    return totalAmount;
}

 

totalAmount 필드는 엔티티 클래스 내에서 주문 총액을 계산하고 저장하는데 사용되지만, 이 값은 엔티티가 영속성 컨텍스트 내에서 활성 상태일 때에만 유효하며, 데이터베이스에는 영구적으로 저장되지 않는다.

 

---

24년 2월 5일 작성된 글입니다