본문 바로가기

백엔드 개발/JPA

[하이버네이트 유저 가이드 파헤치기] @Formula - 2.3.20

반응형

2.3.20. @Formula

때때로, 당신은 JVM보다 데이터베이스가 어떤 계산을 수행하는 것을 원할 때 당신은 가상 칼럼의 일종을 만들 수 있다. 

당신은 데이터베이스 칼럼으로 매핑되는 엔티티 속성 대신 SQL 조각(formula라고 불림)을 엔티티 속성으로 사용할 수 있다.

이 속성은 읽기 전용이다. (이 속성의 값은 당신이 선언한 formula fragment에 의해 계산된다.)

 

당신은 @Formula 어노테이션이 데이터베이스 이식성에 영향을 미치는 native SQL 문을 사용하는 것을 인지해야한다.

(필자 해설: JPQL이 아니라 native SQL이기 때문에 RDBMS의 종류를 교체하는 경우 이식성에 안 좋을 수 있다는 의미)

 

원문
Sometimes, you want the Database to do some computation for you rather than in the JVM, you might also create some kind of virtual column. You can use a SQL fragment (aka formula) instead of mapping a property into a column. This kind of property is read-only (its value is calculated by your formula fragment)

You should be aware that the @Formula annotation takes a native SQL clause which may affect database portability.

 

Example 81. @Formula mapping usage

@Entity(name = "Account")
public static class Account {

	@Id
	private Long id;

	private Double credit;

	private Double rate;

	@Formula(value = "credit * rate")
	private Double interest;

	//Getters and setters omitted for brevity

}

 

Account 엔티티를 로딩할 때, 하이버네이트는 설정된 @Formula를 사용하여 interest 속성값을 계산할 것이다.

(원문: When loading the Account entity, Hibernate is going to calculate the interest property using the configured @Formula:)

 

Example 82. Persisting an entity with a @Formula mapping

doInJPA( this::entityManagerFactory, entityManager -> {
	Account account = new Account( );
	account.setId( 1L );
	account.setCredit( 5000d );
	account.setRate( 1.25 / 100 );
	entityManager.persist( account );
} );

doInJPA( this::entityManagerFactory, entityManager -> {
	Account account = entityManager.find( Account.class, 1L );
	assertEquals( Double.valueOf( 62.5d ), account.getInterest());
} );
INSERT INTO Account (credit, rate, id)
VALUES (5000.0, 0.0125, 1)

SELECT
    a.id as id1_0_0_,
    a.credit as credit2_0_0_,
    a.rate as rate3_0_0_,
    a.credit * a.rate as formula0_0_
FROM
    Account a
WHERE
    a.id = 1

 

@Formula 어노테이션에 의해 정의된 SQL 조각은 당신의 요구에 따라 복잡해질 수 있다.

(심지어 @Formula 어노테이션에 subselect를 포함할 수도 있다.)

(원문: The SQL fragment defined by the @Formula annotation can be as complex as you want, and it can even include subselects.)

 


부록

1. @Formula를 이용한 카운트 성능 최적화

하이버네이트 유저가이드에서 간단하게 언급만한 subselect를 이용해 엔티티 카운트 조회 성능을 개선할 수 있다.

아래 글을 꼭 읽어보기 바란다.

jpa 엔티티 카운트 성능 개선하기

2. @Formula에 지연 로딩(Lazy loading )적용하기

지연 로딩을 적용할 속성이나 getter에 @Basic(fetch=FetchType.LAZY) 어노테이션을 사용해서 적용할 수 있다.

다만, Bytecode Enhancement를 추가로 설정해줘야지 동작한다.

설정 방법은 각 빌드툴마다 다르다.

참고

반응형