EntityGraph とは
JPA 2.1 で標準化された、Entity のフェッチ戦略として EAGER / LAZY を個別に設定できる EntityGraph。
EntityGraph<Employee> graph = em.createEntityGraph(Employee.class); graph.addAttributeNodes(Employee_.salary, Employee_.address); TypedQuery<Employee> query = em.createQuery("SELECT e FROM Employee e ...", graph); query.setHint("javax.persistence.fetchgraph", graph); List<Employee> results = query.getResultList();
ちなみに、ヒントの javax.persistence.loadgraph
は、EntityGraph で未指定のものは Entity の事前定義に従い、javax.persistence.fetchgraph
は、EntityGraph で未指定のものは LAZY 扱いとなる。
上記例では、salary
と address
が EAGERフェッチされる。
詳細は以下
@MappedSuperclass のフィールドは指定できない
問題となるのは @MappedSuperclass
で定義された Entity
@MappedSuperclass public abstract class BaseEntity { @Id private Long id; } @Entity public class Employee extends BaseEntity { private Long salary; @OneToOne(fetch = FetchType.LAZY) private Address address; }
以下のように親クラスのフィールドをグラフに追加できない。
EntityGraph<Employee> graph = em.createEntityGraph(Employee.class); graph.addAttributeNodes(Employee_.id); // compile error !!
もちろん以下のようにはできるが、これでは意味がない。
EntityGraph<BaseEntity> graph = em.createEntityGraph(BaseEntity.class);
graph.addAttributeNodes(BaseEntity_.id);
この時のスタティックメタモデルは以下で、スタティックメタモデル間での継承関係は有る。
@StaticMetamodel(BaseEntity.class) public abstract class BaseEntity_ { public static volatile SingularAttribute<BaseEntity, Long> id; } @StaticMetamodel(Employee.class) public class Employee_ extends BaseEntity_ { public static volatile SingularAttribute<Employee, Long> salary; public static volatile SingularAttribute<Employee, address> address; }
EntityGraph の API バグと回避法
原因は EntityGraph の API が以下の定義となっているため。
public interface EntityGraph<T> { /** * Add one or more attribute nodes to the entity graph. * * @param attribute attribute * @throws IllegalStateException if the EntityGraph has been * statically defined */ public void addAttributeNodes(Attribute<T, ?> ... attribute); }
以下のような定義であるべき。
public interface EntityGraph<T> { void addAttributeNodes(Attribute<? super T, ?>... attribute); }
一応、課題に計上されているが、APIとして公開済みであり、修正は期待できそうにない。
https://github.com/eclipse-ee4j/jpa-api/issues/112
2023年11月追記
上記の誤ったAPIシグネチャはincorrect generic typing in operations of EntityGraphにて対応されました。
利用可能となるのは Jakarta Persistence 3.2 で、Jakarta EE 11 に含まれる予定です。
ワークアラウンドとして、型情報を無視して以下のようにすることは可能。
EntityGraph<Employee> graph = em.createEntityGraph(Employee.class); Attribute attr = Employee_.id; graph.addAttributeNodes(attr);