什么是@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;
}

是一个 java 类,它具有以下定义:Address.class

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

您能解释一下 注释 和 的用途吗?这可能很简单,但我无法理解。@StaticMetamodel@SingularAttribute


答案 1

根据文档

静态元模型是一系列类,它们“镜像”域模型中的实体和可嵌入对象,并提供对有关镜像类属性的元数据的静态访问。

静态元模型具有以下属性:

  • 对于包中的每个托管类,包中都会创建一个元模型类。XpX_p
  • 对于类声明的每个持久非集合值属性,其中 的类型为 ,元模型类必须包含如下声明:yXyY

SingularAttribute例:

public static volatile SingularAttribute<X, Y> y;

静态元模型对于使用 JPA 的条件 API 创建类型安全查询非常有用。

例如,让我们有以下两个实体,并且:OrderItem

@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_.idOrder_.item


答案 2

我最近一直在思考这个问题,因为我一直在努力学习和理解JPA。我相信我对你的问题有一个答案:为什么我们需要MetaModels,为什么我们不能只使用实体模型?

看看这个实体:

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

    int quantity;

    @ManyToOne
    Order order;

    // accessors
}

请注意,实体上的任何属性都没有关键字 static。这意味着为了使用它们,我们需要创建一个新的对象。

当我们使用 CriteriaBuilder 构建查询时,我们不需要创建对象...我们只想使用实体上的属性来生成查询。这就是我们拥有MetaModels的原因!它们创建静态属性,我们无需创建对象即可访问这些属性。因此,我们可以做像康斯坦丁提到的那样的事情:

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”对象...我们只需要知道它的性质。MetaModel上的静态属性使我们能够做到这一点!


推荐