9 Ocak 2019 Çarşamba

JPA @StaticMetamodel Anotasyonu

Giriş
Şu satırı dahil ederiz.
import javax.persistence.metamodel.ListAttribute;
import javax.persistence.metamodel.SingularAttribute;
import javax.persistence.metamodel.StaticMetamodel;
Açıklaması şöyle
A static metamodel is a series of classes that "mirror" the entities and embeddables in the domain model and provide static access to the metadata about the mirrored class's attributes.
Açıklaması şöyle.
The static metamodel is useful for creating type-safe queries with the JPA's Criteria API.
Sınıf İsmi
Metamodel sınıfının ismi gerçek sınıf ismi + "_" karakteridir. Örneğin "Foo_" gibidir.

Alan İsimleri
Metamodel içinde ListAttribute, SingularAttribute tipinden alanlar olur. Attribute isimler gerçek koddaki ile aynı olmalı. SingularAttribute alan için ilk parametre gerçek sınıf ismi, ikinci parametre alan tipidir.

X sınıfındaki Y tipindne alan tanımlamak için şöyle yaparız.
public static volatile SingularAttribute<X, Y> y;

Örnek
Şu kod attribute ismi + "_" karakterlerini kullandığı için yanlış.
@StaticMetamodel(Foo.class)
public class Foo_{
    ...
    public static volatile SingularAttribute<Foo, String> attribute_;
    public static volatile SingularAttribute<Foo, Bar> bar_;
    ...
}

@StaticMetamodel(Bar.class)
public class Bar_{
    public static volatile SingularAttribute<Bar, Date> time_;
}
Kullanım
CriteriaQuery.join(), Root.get() gibi  metodlarla kullanılır.

Örnek - Root.get()
Şöyle yaparız.
@Override
public Page<Foo> findAllWithPagingAndFilter(PageRequest pageRequest, String attribute) {
  CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
  CriteriaQuery<Foo> criteriaQuery = criteriaBuilder.createQuery(Foo.class);
  Root<Foo> root = criteriaQuery.from(Foo.class);
  Predicate attributePredicate= criteriaBuilder.equal(root.get(Foo_.attribute),attribute);
  criteriaQuery.where(attributePredicate);
  criteriaQuery.orderBy(criteriaBuilder.desc(root.get(Foo_.bar).get(Bar_.time)));
  TypedQuery<Comment> typedQuery = entityManager.createQuery(criteriaQuery);
  typedQuery.setFirstResult((pageRequest.getPageNumber()) * pageRequest.getPageSize());
  typedQuery.setMaxResults(pageRequest.getPageSize());
  return new PageImpl<>(typedQuery.getResultList(), pageRequest,
    genericCountWithPredicates(Foo.class, attributePredicate));
}
Örnek - CriteriaQuery.join()
Şöyle yaparız
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<Order> cq = cb.createQuery(Order.class);
SetJoin<Order, Item> itemNode = cq.from(Order.class).join(Order_.items);
cq.where(cb.equal(itemNode.get(Item_.id), 5)).distinct(true);
Örnek
Şöyle yaparız.
package Entities;

import javax.annotation.Generated;
import javax.persistence.metamodel.SingularAttribute;
import javax.persistence.metamodel.StaticMetamodel;

@Generated(value="EclipseLink-2.5.2.v20140319-rNA", date="2018-03-20T16:09:40")
@StaticMetamodel(Item.class)
public class Item_ { 

  public static volatile SingularAttribute<Item, Long> item_id;
  public static volatile SingularAttribute<Item, Long> b_id;
  public static volatile SingularAttribute<Item, Double> item_price;
  public static volatile SingularAttribute<Item, String> description;
  public static volatile SingularAttribute<Item, String> item_name;
  public static volatile SingularAttribute<Item, String> manufacturer;

}
Aynı şeyin Order için de yapıldığını varsayalım. Şöyle yaparız. Order_ ve Item_ sınıfları StaticMetamodel ile tanımlıdır.
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<Order> cq = cb.createQuery(Order.class);
SetJoin<Order, Item> itemNode = cq.from(Order.class).join(Order_.items);
cq.where(cb.equal(itemNode.get(Item_.id), 5)).distinct(true);
Örnek
Elimizde şöyle bir kod olsun.
@Generated(value = "org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor")
@StaticMetamodel(ReadModel.class)
public abstract class ReadModel_  {

  public static volatile SingularAttribute<ReadModel, Time> time;
  public static volatile SingularAttribute<ReadModel, BigInteger> customerId;
  public static volatile SingularAttribute<ReadModel, BigInteger> deviceId;
  public static volatile SingularAttribute<ReadModel, Timestamp> deviceTime;
  public static volatile SingularAttribute<ReadModel, Date> date;
} 
Elimizde şöyle bir kod olsun.
@StaticMetamodel(DeviceData.class)
public abstract class DeviceData_ extends ReadModel_ {
  public DeviceData_() {
  }
}
Şöyle yaparız.
CriteriaBuilder cb = session.getCriteriaBuilder();
CriteriaQuery<DeviceData> cq = cb.createQuery(DeviceData.class);
Root<DeviceData> root = cq.from(DeviceData.class);
List<Predicate> conditions = new ArrayList<>();
conditions.add(cb.isTrue(root.get(deviceId).in(...)));
conditions.add(cb.greaterThanOrEqualTo(root.get(devicetime), ...));

cq.where(conditions.toArray(new Predicate[]{})).orderBy(cb.asc(root.get(devicetime)));
Query query= session.createQuery(cq);

Hiç yorum yok:

Yorum Gönder