다른분의 코드를 보다가 @Formula라는 어노테이션을 보았다. 그분 코드를 보니 약간 좋아요수를 불러오는 것같던데 근데 엥?? 엔티티에 @Formula가 있길래 이게 뭐야...? 라는 느낌에 찾아보았다
@Formula
하이버네이트 사이트에 들어가서 보면 이렇게 적혀져 있다
@Formula
allows mapping any database computed value as a virtual read-only column.
The @Formula annotation takes a native SQL clause which may affect database portability.
@Formula is a Hibernate-specific mapping construct and not covered by Jakarta Persistence. Applications interested in portability should avoid its use.
한마디로 JPA상에는 존재하지만 DB에는 생성되지 않는 칼럼인 가상 칼럼이고 읽기전용 칼럼이다.
이 어노테이션은 데이터의 이식성에 영향을 주는 native sql문을 사용한다. (즉 jpql이 아니라 native sql이기에 rdms 종료 변경시 이식성이 안좋다는 의미인것같다)
예시
예시 1)
@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
}
와같이 가상 칼럼을 만들어 사용가능하다. 그래서 만약 조회를 하게 된다면
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
이렇게 나올 것이다
에시 2) 컬렉션 수 반환하기
예를들어 간접참조이거나 지연로딩일때 관련 엔티티에 대해서 사이즈가 필요할때가 있다. 뭐 좋아요 수라든지, 부서수라든지
지연로딩같은경우 실제 사용 시점에서 데이터를 조회한다.
그래서 만약 카운트만을 조회하기 위해 연관엔티티를 사용한다면 데이터가 많아지면 많아질수록 sql실행속도가 늘려질뿐만 아니라 데이터를 담는 컬렉션도 많은 메모리를 사용하기 때문에 점점 성능이 덜어진다. 더 큰 문제는 카운트를 조회시 해당 엔티티의 수만큼 반복한 다는 것이다
이때 @Formula를 사용하기 한다
@Formula("(select count(*) from employee e where e.dept_id = id)")
private int employees;
와 같이 부서에 대한 직원수를 구하기 위해 @Formula를 사용한다
이렇게 조회하게 되면
Hibernate:
select
department0_.id as id1_0_,
department0_.name as name2_0_,
(select
count(*)
from
employee e
where
e.dept_id = department0_.id) as formula0_)
from
Department department0_
이렇게 Formula가 기본적으로 fetchType.Eager로 가져오게 된다
물론 Formula도 지연로딩이 가능하다. 적용할 속성이나 getterdp @Basic(fetch=FetchType.Lazy) 를 적용하면 된다
다만 Bytecode Enhancement를 추가로 설정해줘야 동작한다
Bytecode Enhancement 이 아이에 대해서는 다음에 설명하도록 하겠다...
'개발 이론 > JPA' 카테고리의 다른 글
JpaRepository를 상속하지 않는다. (0) | 2024.05.12 |
---|---|
영속성 컨텍스트와 트랜젝션 (0) | 2023.12.29 |
[JPA] 프록시에 대하여 (1) | 2023.11.12 |
[JPA] JPA 와 Hibernate , Spring Data JPA (0) | 2023.11.10 |
[JPA] JPA엔티티에 기본생성자가 필요하다? (0) | 2023.11.10 |