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
类型。