JPA 实体未从 EJB 正确传递到表示层
JPA entity is not correctly passed from EJB to Presentation Tier
我正在尝试将一组 JPA 实体从业务层传递到表示层。所有这些都部署在同一个应用程序服务器 (Glassfish 4) 上。客户端部署为 .war 文件,而业务层部署为 .ear,ejb 可通过远程接口访问。
为此我有那些非常简单的方法,完全没有逻辑:
客户
public List<CompletedDesign> selectCompletedDesigns() {
try {
List<CompletedDesign> designs = customerFacade.selectCompletedDesigns();
return designs;
} catch (EJBException e) {
e.printStackTrace();
}
return null;
}
而在 ejb
// EJB
@Override
@RolesAllowed("customer")
public List<CompletedDesign> selectCompletedDesigns() {
final Principal callerPrincipal = sessionCtx.getCallerPrincipal();
String name = callerPrincipal.getName();
Customer customer = dataXchangeBean.getCustomerByID(name);
List<CompletedDesign> cds = customerBean.selectCompletedDesigns(customer);
return cds;
}
最后这是 JPA 实体的一个片段。
@Entity
@Table(name = "COMPLETED_DESIGN")
@NamedQueries({......})
public class CompletedDesign implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@Basic(optional = false)
@NotNull
@Size(min = 1, max = 20)
@Column(name = "ID")
private String id;
@Column(name = "DESCRIPTION")
private String description;
@Column(name = "NAME")
private String name;
@Column(name = "STATUS")
private DesignStatus status;
@JoinColumn(name = "CUSTOMER_FK", referencedColumnName = "ID")
@ManyToOne(optional = false, fetch = FetchType.LAZY)
private Customer customerFk;
@OneToMany(cascade = CascadeType.ALL, mappedBy = "designFk", fetch = FetchType.LAZY)
private List<Product> products;
通过设置断点,我可以看到 cds
列表在 EJB 端被正确检索。第一个问题是,为什么我得到的是 Vector 而不是 List ?我正在使用来自 JPS 端的 TypedQuery,它应该可以正确地转换对象。
不过我主要担心的是:后续断点在客户端class本身在表现层,好像不能完全重构对象,值都是null,类型是丢失的。我在这里错过了什么?
您正在使用 LAZY 加载,这意味着相关对象将在您访问它们时加载,而不是在加载主要对象时加载(这样如果您真的不需要它们就不会加载)。但是,当主要对象从会话中分离时,这不起作用。因此,在通过远程接口传递之前,您必须使用 EAGER 而不是惰性,或者只加载(访问)您在事务中需要的集合。
在花了几天时间尝试让它工作之后,我发现了这个 SO post,它带来了最明显的解决方案,Glassfish 和 EclipseLink 的一个错误!!!
SO post:
EclipseLink deserializes an empty entity object on remote EJB call
我正在尝试将一组 JPA 实体从业务层传递到表示层。所有这些都部署在同一个应用程序服务器 (Glassfish 4) 上。客户端部署为 .war 文件,而业务层部署为 .ear,ejb 可通过远程接口访问。
为此我有那些非常简单的方法,完全没有逻辑:
客户
public List<CompletedDesign> selectCompletedDesigns() {
try {
List<CompletedDesign> designs = customerFacade.selectCompletedDesigns();
return designs;
} catch (EJBException e) {
e.printStackTrace();
}
return null;
}
而在 ejb
// EJB
@Override
@RolesAllowed("customer")
public List<CompletedDesign> selectCompletedDesigns() {
final Principal callerPrincipal = sessionCtx.getCallerPrincipal();
String name = callerPrincipal.getName();
Customer customer = dataXchangeBean.getCustomerByID(name);
List<CompletedDesign> cds = customerBean.selectCompletedDesigns(customer);
return cds;
}
最后这是 JPA 实体的一个片段。
@Entity
@Table(name = "COMPLETED_DESIGN")
@NamedQueries({......})
public class CompletedDesign implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@Basic(optional = false)
@NotNull
@Size(min = 1, max = 20)
@Column(name = "ID")
private String id;
@Column(name = "DESCRIPTION")
private String description;
@Column(name = "NAME")
private String name;
@Column(name = "STATUS")
private DesignStatus status;
@JoinColumn(name = "CUSTOMER_FK", referencedColumnName = "ID")
@ManyToOne(optional = false, fetch = FetchType.LAZY)
private Customer customerFk;
@OneToMany(cascade = CascadeType.ALL, mappedBy = "designFk", fetch = FetchType.LAZY)
private List<Product> products;
通过设置断点,我可以看到 cds
列表在 EJB 端被正确检索。第一个问题是,为什么我得到的是 Vector 而不是 List ?我正在使用来自 JPS 端的 TypedQuery,它应该可以正确地转换对象。
不过我主要担心的是:后续断点在客户端class本身在表现层,好像不能完全重构对象,值都是null,类型是丢失的。我在这里错过了什么?
您正在使用 LAZY 加载,这意味着相关对象将在您访问它们时加载,而不是在加载主要对象时加载(这样如果您真的不需要它们就不会加载)。但是,当主要对象从会话中分离时,这不起作用。因此,在通过远程接口传递之前,您必须使用 EAGER 而不是惰性,或者只加载(访问)您在事务中需要的集合。
在花了几天时间尝试让它工作之后,我发现了这个 SO post,它带来了最明显的解决方案,Glassfish 和 EclipseLink 的一个错误!!!
SO post: EclipseLink deserializes an empty entity object on remote EJB call