Что такое @StaticMetamodel и SingularAttribute <Obj, Obj>?

Я пытаюсь выяснить этот код около двух часов, например, в нижележащем классе, что представляют собой эти поля?

import java.util.Date;
import javax.persistence.metamodel.ListAttribute;
import javax.persistence.metamodel.SingularAttribute;
import javax.persistence.metamodel.StaticMetamodel;
import java.util.UUID;

@StaticMetamodel(Address.class)
public class Address_ extends  {
    public static volatile SingularAttribute<Address, Long> id;
    public static volatile SingularAttribute<Address, UUID> personId;
    public static volatile SingularAttribute<Address, Person> person;
}

Address.class - это класс java, который имеет следующее определение:

@Entity
@Table(name = "address", schema = "public")
public class Address{
    private Long id;
    private Person person;
    private UUID personId;
    //....
}

Можете ли вы объяснить, для чего используются аннотации @StaticMetamodel и @SingularAttribute? Это может быть просто, но я не понимаю.

Ответы

Ответ 1

По документация:

Статическая метамодель представляет собой серию классов, которые "зеркалируют" объекты и встраиваемые в модель домена и обеспечивают статический доступ к метаданные о атрибутах зеркального класса.

Статическая метамодель обладает следующими свойствами:

  • Для каждого управляемого класса X в пакете p создается класс метамодели X_ в пакете p.
  • Для каждого сохраняемого атрибута y, не относящегося к коллекции, объявленного классом X, где тип y равен y, класс метамодели должен содержать объявление следующим образом:

SingularAttribute пример:

public static volatile SingularAttribute<X, Y> y;

Статическая метамодель полезна для создания запросов типа с API-интерфейсом JPA.

Например, пусть имеют следующие два объекта: Order и Item:

@Entity
public class Order {
    @Id 
    @GeneratedValue
    Integer id;

    @ManyToOne 
    Customer customer;

    @OneToMany 
    Set<Item> items;

    BigDecimal totalCost;

    // accessors
}

и объект Item:

@Entity  
public class Item { 
    @Id
    @GeneratedValue
    Integer id;

    int quantity;

    @ManyToOne
    Order order;

    // accessors
}

Здесь запрограммирован тип критериев, построенный с помощью API критериев:

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);

Обратите внимание на использование Item_.id и Order_.item. Они статически статически статические свойства метамодели (которые отражают свойства объекта), и таким образом они гарантируют правильную сборку запроса.