JPA 透明间接和容器策略
Posted
技术标签:
【中文标题】JPA 透明间接和容器策略【英文标题】:JPA Transparent Indirection and Container Policies 【发布时间】:2014-07-24 02:28:06 【问题描述】:假设我有以下简单的客户/订单实现:
由 Customer 类定义的客户记录。 每个客户可以有多个由 Order 类定义的订单。
借鉴here对透明间接和容器策略的解释here我对EclipseLink这些概念的理解如下:
透明间接允许我说
Customer customer = Customer.getCustomerById(1);
Set<Order> orders = customer.getOrders();
需要注意的两点是:
-
间接允许延迟加载属性,因此客户的订单仅在第 2 行而不是第 1 行从数据库中获取。
我可以将客户的订单视为 Order 类型对象的 Set(或 Collection、List 或 Map)。
Container Policy 告诉 EclipseLink 应该为 Set 使用哪个实际类,因此它应该在上面的示例中实现 Set
。
这就是我对 EclipseLink 中透明间接和容器策略的理解。
我在尝试访问数据库时看到以下错误:
异常 [EclipseLink-148] (Eclipse Persistence Services - 2.3.0.v20110604-r9504): org.eclipse.persistence.exceptions.DescriptorException 异常描述:容器策略 [CollectionContainerPolicy(class org.eclipse.persistence.indirection.IndirectSet)] 与透明间接不兼容。 映射:org.eclipse.persistence.mappings.OneToManyMapping[orders] 描述符:RelationalDescriptor(my.model.Customer --> [DatabaseTable(Customer)])
我确定我在尝试调试的代码中有错误,但我没有指定错误中提到的 CollectionContainerPolicy,所以我假设 org.eclipse.persistence.indirection.IndirectSet
是默认值。但如果我使用的是默认策略,那么我不确定这个错误的原因可能是什么,或者我应该使用哪个策略。
现在,我只想知道我对上面提到的透明间接和容器策略的理解是否正确。
如果它是正确的,我可能在我的代码中遗漏了一些相对较小的东西(调用或配置选项等),但如果我不理解这些概念,那么显然我需要先做更多的研究。
客户模型
package my.model;
import java.io.Serializable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;
import javax.persistence.Table;
/**
* The persistent class for the customer database table.
*
*/
@Entity
@Table(name=Customer.TBL_NAME)
@NamedQueries(
@NamedQuery(name=Customer.QRY_BY_NAME,query="Select object(a) from Customer a where " +
"a.name=:" + Customer.PRM_NAME),
@NamedQuery(name=Customer.QRY_ALL, query="select object(a) from Customer a")
)
public class Customer implements Serializable
private static final long serialVersionUID = 1L;
// Table specific onstants
public static final String TBL_NAME = "Customer";
public static final String QRY_BY_NAME = TBL_NAME + ".byName";
public static final String QRY_ALL = TBL_NAME + ".all";
public static final String PRM_NAME = "name";
private int id;
private String name;
private Set<Order> orders;
public Customer()
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
public int getId()
return this.id;
public void setId(int id)
this.id = id;
public String getName()
return this.name;
public void setName(String name)
this.name = name;
//bi-directional many-to-one association to Order
@OneToMany(mappedBy="customer")
public Set<Order> getOrders()
return this.orders;
public void setOrders(Set<Order> orders)
this.orders = orders;
订单型号
package my.model;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
/**
* The persistent class for the order database table.
*
*/
@Entity
@Table(name=Order.TBL_NAME)
public class Order implements Serializable
private static final long serialVersionUID = 1L;
// Table constants
public static final String TBL_NAME = "Order";
private int id;
private Customer customer;
public Order()
@Id
public int getId()
return this.id;
public void setId(int id)
this.id = id;
//bi-directional many-to-one association to Customer
@ManyToOne
public Customer getCustomer()
return this.customer;
public void setCustomer(Customer customer)
this.customer = customer;
【问题讨论】:
你能展示你的实体和映射吗?你是怎么配置的? 感谢您查看此内容。我不想陷入代码中,我希望先确认我的理解。但是,我已经添加了模型定义,所以如果您发现它们有问题,请告诉我。 您的理解是正确的,但不应该需要,因为这不是您在使用 JPA 时需要配置的东西。 EclipseLink 将根据属性的类型和惰性/急切设置来确定要使用的收集策略和实现,而且它似乎这样做是正确的。异常抛出错误,可能是由于类加载器问题,因此用于 init 的类加载器不是用于验证的类加载器,但我不知道这是怎么发生的。您需要查看它运行的环境,因为异常本身只是一种症状。 谢谢,这是一个非常明确的答案。我注意到其他人也面临类似的问题,以及 Glassfish 的其他类加载器问题。如果您认为这个问题不是太琐碎,请将您的最后一条评论作为答案发表,我会将其标记为我接受的答案。 【参考方案1】:您的理解是正确的,但不需要,因为这不是您在使用 JPA 时需要配置的内容。 EclipseLink 将根据属性的类型和惰性/急切设置来确定要使用的收集策略和实现,而且它似乎这样做是正确的。异常抛出错误,可能是由于类加载器问题,因此用于 init 的类加载器不是用于验证的类加载器,但我不知道这是怎么发生的。您需要查看它运行的环境,因为异常本身只是一种症状
【讨论】:
以上是关于JPA 透明间接和容器策略的主要内容,如果未能解决你的问题,请参考以下文章
如何将继承策略与 JPA 注释和 Hibernate 混合使用?