RequestFactory Entity的参数:List 在客户端上为null。 在服务器上没问题

我正在学习RequestFactory。 我有一个简单的例子。 现在我想从下面为RF实现这些实体:


服务器包

@Entity public class Pizza implements Identifiable, Versionable { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Version private Long version; private String name; @ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER) private List ingredients; /* Getters and Setters */ } @Entity public class Ingredient implements Identifiable, Versionable { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Version private Long version; private String name; private boolean vegan; /* Getters and Setters */ } 

这是Pizza Entity DAO类:

 @Override public List get() { CriteriaBuilder cb = JPA.em().getCriteriaBuilder(); CriteriaQuery q = cb.createQuery(Pizza.class); Root c = q.from(Pizza.class); q.select(c); TypedQuery query = JPA.em().createQuery(q); List results = query.getResultList(); for(Pizza p: results) { for(Ingredient i: p.getIngredients()) { logger.info(i.getName()); } } return results; } 

共享包

我为这些课写了Proxies:

 @ProxyFor(value = Pizza.class, locator = PizzaLocator.class) public interface PizzaProxy extends EntityProxy { public Long getId(); public String getName(); public void setName( String name ); public Long getVersion(); public List getIngredients(); public void setIngredients( List ingredients ) } @ProxyFor(value = Ingredient.class) public interface IngredientProxy extends EntityProxy { public void setId(Long id); public Long getId(); public Long getVersion(); public void setVersion(Long version); public String getName(); public void setName(String name); public boolean isVegan(); public void setVegan(boolean vegan); } 

射频相关接口:

 public interface RequestFactoryServices extends RequestFactory { PizzaRequest pizzaRequest(); } @Service(value = PizzaDao.class, locator = DaoLocator.class) public interface PizzaRequest extends RequestContext { Request findById( Long id ); Request save( PizzaProxy pizza ); Request<List> get(); } 

客户端包

这是我从服务器获取数据的方式:

 List pizzas = new LinkedList(); PizzaRequest context = createFactory().pizzaRequest(); context.get().to(new Receiver<List>() { @Override public void onSuccess(List response) { for(PizzaProxy p: response) { RootPanel.get().add(new Label( p.getId() + " " + p.getName() + ", " + p.getVersion() + ", " + p.getIngredients() )); } } }).fire(); 

正如您在get()方法中的DAO类中所看到的,我正在打印有关成分的记录器信息。 在服务器端它一切正常。

问题是,当我调用p.getIngredients()我得到null ,而不是IngredientsProxies列表。

是不是因为我没有Ingredients实体的Dao和Locator类?

请帮忙。

答案:实体关系

对相关实体的更改可以保留在单个请求中。 例如,来自GWT trunk中的DynatableRF示例应用程序的代码同时创建一个新的Person和Address:

PersonRequest context = requestFactory.personRequest(); AddressProxy address = context.create(AddressProxy.class); PersonProxy person = context.create(PersonProxy.class); person.setAddress(地址); context.persist()使用(人).fire(…)。 RequestFactory在单个请求中自动发送整个对象图。 在这种情况下,服务器上Person.persist()的实现也负责持久保存相关地址,这可能会也可能不会自动发生,具体取决于ORM框架以及如何定义关系。 请注意,RequestFactory当前不支持嵌入式对象(@Embedded在各种ORM框架中),因为它希望每个实体都独立存在并具有自己的ID。

查询服务器时,RequestFactory不会自动填充对象图中的关系。 为此,请对请求使用with()方法,并将相关属性名称指定为String:

请求findReq = requestFactory.personRequest()。find(personId).with(“address”); 还必须使用with()方法来检索具有扩展ValueProxy的类型的任何属性。 with()方法接受多个String参数,因此您可以一次指定多个属性名称。 要指定嵌套属性,请使用点表示法。 把它们放在一起,你可能会

请求findReq = find(personId).with(“phone”,“address.city”,“address.zip”)

默认情况下,gwt在获取对象时不会附加集合实体。 你需要在你的射频请求中使用.with(“成分”)。 确保您的披萨类中有getIngredients方法。 rf请求上下文将使用它来获取成分。 如果你从hibernate这样的东西中获取它,你可能还需要确保打开一个事务。 这将确保rf上下文在检索披萨的成分时可以使用附加实体。

请注意,您不希望使用with(“getIngredients”)rf上下文将正确调用get方法。

 context.get().with("ingredients").fire(new Receiver<>) 

默认情况下,RequestFactory不会递归导致提取,以保存线路上的数据库调用和空间。

如果您需要ingredients属性,您必须提出要求。 代替

 context.get().to(... 

在那里添加对Request.with(String... propertyRefs)的调用,并指定你想要的成分:

 context.get().with("ingredients").to(... 

没有为Ingredients类型定位器可能最终会产生问题,但如果您尝试以这样的方式使用这些对象,您需要使用Locator或类中的静态方法。 您不需要特定的DAO和ServiceLocator类,除非您最终为它创建RequestContext类型。