我正在尝试使用JPA Criteria API进行非常简单的查询。
我有两个实体:
@Entity
@Table(name = "PERSONS")
public class Person implements Serializable
{
@Id
@Column(name = "COD_PERSON")
private String personCode;
@Column(name = "NAME")
private String name;
@OneToMany(mappedBy="person")
List<Address > addresses;
... other attributes, getters and setters
}
@Entity
@Table(name = "ADDRESS")
public class Address implements Serializable
{
private static final long serialVersionUID = 1L;
@Id
@Column(name = "COD_ADDRESS")
private String addressCode;
@ManyToOne(fetch=FetchType.LAZY, optional=false)
@JoinColumn(name = "COD_PERSON")
private Person person;
@Column(name = "street")
private String street;
@Column(name = "zipCode")
private String zipCode;
... other attributes, getters and setters
}
我们在“地址”实体中定义了ManyToOne关联,在“人”实体中定义了OneToMany关联。由于性能问题,两者都被定义为懒惰。
然后,例如,我想查询居住在某个邮政编码中的人。我想让人们知道他们的地址。
因为我们将关联定义为惰性,并且因为“地址”是OneToMany关联,所以我认为我应该使用“ eclipselink.batch”提示。
我尝试过:
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Person> query = cb.createQuery(Person.class);
Root<Person> from = query.from(Person.class);
Join<Person, Address> join = from.join("addresses");
query.select(from);
Predicate predicate = cb.equal(join .get("zipCode"), "28020");
query.where(predicate);
List results = em.createQuery(query).setHint(org.eclipse.persistence.config.QueryHints.BATCH, "p.addresses").getResultList();
我得到所有居住在特定邮政编码中的人,这没关系,但是没有填充'addreses'属性。
如何获取填充了“ addreses”属性的“ person”实体?
谢谢
我找到的解决方案:
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Person> query = cb.createQuery(Person.class);
Root<Person> from = query.from(Person.class);
Join<Person, Address> join = (Join<Person, Address>) from.fetch("addresses", JoinType.LEFT);
query.select(from);
Predicate predicate = cb.equal(join.get("zipCode"), "28020");
query.where(predicate);
List results = em.createQuery(query).getResultList();
我不是很喜欢我要做的演员。我已经尝试使用EclipseLink提供程序。我不知道它是否可以与其他提供商一起使用。
答案 0 :(得分:2)
您可以在“ Root”类上使用“ fetch”方法。
例如
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery q = cb.createQuery(Order.class);
Root o = q.from(Order.class);
o.fetch("items", JoinType.INNER);
q.select(o);
q.where(cb.equal(o.get("id"), orderId));
Order order = (Order)this.em.createQuery(q).getSingleResult();
此外,您还可以从此处检查其他选项
https://www.thoughts-on-java.org/5-ways-to-initialize-lazy-relations-and-when-to-use-them/
编辑1:
我创建了一个使用'fetch'方法的简单示例。你可以退房 从下面的链接。
https://github.com/sonerokur/stackoverflow-51375238/
编辑2:
您可以提取联接,这样只能导致一个联接,如下所示:
...
Join<Order, OrderItem> join = (Join<Order,OrderItem>)root.<Order,OrderItem>fetch("items");
...
编辑3:
如果您不想使用强制转换,则可以使用实体图。但是,此解决方案自JPA 2.1起可用
...
EntityGraph<Order> fetchGraph = entityManager.createEntityGraph(Order.class);
fetchGraph.addSubgraph("items");
TypedQuery<Order> orderQuery = entityManager.createQuery(query);
orderQuery.setHint("javax.persistence.loadgraph", fetchGraph);
...