RequestFactory 实体的参数:List<OfOtherEntity> 在客户端上为空。在服务器上没问题
RequestFactory Entity's parameter: List<OfOtherEntity> is null on client. On server is ok
我正在学习 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<Ingredient> 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 */
}
这里是 DAO
class Pizza Entity
:
@Override
public List<Pizza> get() {
CriteriaBuilder cb = JPA.em().getCriteriaBuilder();
CriteriaQuery<Pizza> q = cb.createQuery(Pizza.class);
Root<Pizza> c = q.from(Pizza.class);
q.select(c);
TypedQuery<Pizza> query = JPA.em().createQuery(q);
List<Pizza> results = query.getResultList();
for(Pizza p: results) {
for(Ingredient i: p.getIngredients()) {
logger.info(i.getName());
}
}
return results;
}
共享包
我为那些 classes:
写了代理
@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<IngredientProxy> getIngredients();
public void setIngredients( List<IngredientProxy> 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<PizzaProxy> findById( Long id );
Request<Void> save( PizzaProxy pizza );
Request<List<PizzaProxy>> get();
}
客户端包
这是我从服务器获取数据的方式:
List<PizzaProxy> pizzas = new LinkedList<PizzaProxy>();
PizzaRequest context = createFactory().pizzaRequest();
context.get().to(new Receiver<List<PizzaProxy>>() {
@Override
public void onSuccess(List<PizzaProxy> response) {
for(PizzaProxy p: response) {
RootPanel.get().add(new Label(
p.getId() + " " +
p.getName() + ", " +
p.getVersion() + ", " +
p.getIngredients()
));
}
}
}).fire();
正如您在 DAO
class 中看到的 get()
方法,我正在打印以记录有关成分的信息。在服务器端一切正常。
问题是,当我调用 p.getIngredients()
时,我得到的是 null
,而不是 IngredientsProxies
.
的列表
发生这种情况是因为我没有 Ingredients
实体的 Dao 和定位器 classes 吗?
请帮忙。
回答:
实体关系
对相关实体的更改可以保存在单个请求中。例如,这段来自 GWT trunk 中 DynatableRF 示例应用程序的代码同时创建了一个新的 Person 和 Address:
PersonRequest 上下文 = requestFactory.personRequest();
地址代理地址=context.create(AddressProxy.class);
PersonProxy person = context.create(PersonProxy.class);
person.setAddress(地址);
context.persist().using(person).fire(...);
RequestFactory 在单个请求中自动发送整个对象图。在这种情况下,服务器上 Person.persist() 的实现也负责持久化相关地址,这可能会自动发生,也可能不会自动发生,具体取决于 ORM 框架以及关系的定义方式。请注意,RequestFactory 目前不支持嵌入式对象(@Embedded 在各种 ORM 框架中),因为它希望每个实体都独立存在并具有自己的 ID。
查询服务器时,RequestFactory 不会自动填充对象图中的关系。为此,请在请求中使用 with() 方法并将相关的 属性 名称指定为字符串:
请求 findReq = requestFactory.personRequest().find(personId).with("address");
还需要使用 with() 方法来检索具有扩展 ValueProxy 类型的任何属性。 with() 方法接受多个字符串参数,因此您可以一次指定多个 属性 名称。要指定嵌套属性,请使用点表示法。把它们放在一起,你可能有
请求 findReq = find(personId).with("phone","address.city","address.zip")
默认情况下,RequestFactory 不会递归地导致提取发生,以保存数据库调用和在线 space。
如果您需要 ingredients
属性,您必须申请。而不是
context.get().to(...
在其中添加对 Request.with(String... propertyRefs)
的调用,并指定您想要的成分:
context.get().with("ingredients").to(...
没有 Ingredients
类型的定位器可能最终会变得很重要,但如果您尝试以 Locator
或静态的方式使用这些对象,您将得到特定的错误class 中的方法是必需的。你不需要特定的 DAO 和 ServiceLocator
class 除非你最终为它创建一个 RequestContext
类型。
默认情况下,gwt 在获取对象时不附加集合实体。您需要在 rf 请求中使用 .with("ingredients") 。确保你的披萨中有 getIngredients 方法 class。 rf 请求上下文将使用它来获取成分。如果您从休眠之类的东西中获取它,您可能还需要确保打开了一个事务。这将确保 rf 上下文在检索比萨饼的成分时可以使用附加的实体。
请注意,您不想使用 with("getIngredients") rf 上下文将正确调用 get 方法。
context.get().with("ingredients").fire(new Receiver<>)
我正在学习 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<Ingredient> 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 */
}
这里是 DAO
class Pizza Entity
:
@Override
public List<Pizza> get() {
CriteriaBuilder cb = JPA.em().getCriteriaBuilder();
CriteriaQuery<Pizza> q = cb.createQuery(Pizza.class);
Root<Pizza> c = q.from(Pizza.class);
q.select(c);
TypedQuery<Pizza> query = JPA.em().createQuery(q);
List<Pizza> results = query.getResultList();
for(Pizza p: results) {
for(Ingredient i: p.getIngredients()) {
logger.info(i.getName());
}
}
return results;
}
共享包
我为那些 classes:
写了代理@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<IngredientProxy> getIngredients();
public void setIngredients( List<IngredientProxy> 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<PizzaProxy> findById( Long id );
Request<Void> save( PizzaProxy pizza );
Request<List<PizzaProxy>> get();
}
客户端包
这是我从服务器获取数据的方式:
List<PizzaProxy> pizzas = new LinkedList<PizzaProxy>();
PizzaRequest context = createFactory().pizzaRequest();
context.get().to(new Receiver<List<PizzaProxy>>() {
@Override
public void onSuccess(List<PizzaProxy> response) {
for(PizzaProxy p: response) {
RootPanel.get().add(new Label(
p.getId() + " " +
p.getName() + ", " +
p.getVersion() + ", " +
p.getIngredients()
));
}
}
}).fire();
正如您在 DAO
class 中看到的 get()
方法,我正在打印以记录有关成分的信息。在服务器端一切正常。
问题是,当我调用 p.getIngredients()
时,我得到的是 null
,而不是 IngredientsProxies
.
发生这种情况是因为我没有 Ingredients
实体的 Dao 和定位器 classes 吗?
请帮忙。
回答: 实体关系
对相关实体的更改可以保存在单个请求中。例如,这段来自 GWT trunk 中 DynatableRF 示例应用程序的代码同时创建了一个新的 Person 和 Address:
PersonRequest 上下文 = requestFactory.personRequest(); 地址代理地址=context.create(AddressProxy.class); PersonProxy person = context.create(PersonProxy.class); person.setAddress(地址); context.persist().using(person).fire(...); RequestFactory 在单个请求中自动发送整个对象图。在这种情况下,服务器上 Person.persist() 的实现也负责持久化相关地址,这可能会自动发生,也可能不会自动发生,具体取决于 ORM 框架以及关系的定义方式。请注意,RequestFactory 目前不支持嵌入式对象(@Embedded 在各种 ORM 框架中),因为它希望每个实体都独立存在并具有自己的 ID。
查询服务器时,RequestFactory 不会自动填充对象图中的关系。为此,请在请求中使用 with() 方法并将相关的 属性 名称指定为字符串:
请求 findReq = requestFactory.personRequest().find(personId).with("address"); 还需要使用 with() 方法来检索具有扩展 ValueProxy 类型的任何属性。 with() 方法接受多个字符串参数,因此您可以一次指定多个 属性 名称。要指定嵌套属性,请使用点表示法。把它们放在一起,你可能有
请求 findReq = find(personId).with("phone","address.city","address.zip")
默认情况下,RequestFactory 不会递归地导致提取发生,以保存数据库调用和在线 space。
如果您需要 ingredients
属性,您必须申请。而不是
context.get().to(...
在其中添加对 Request.with(String... propertyRefs)
的调用,并指定您想要的成分:
context.get().with("ingredients").to(...
没有 Ingredients
类型的定位器可能最终会变得很重要,但如果您尝试以 Locator
或静态的方式使用这些对象,您将得到特定的错误class 中的方法是必需的。你不需要特定的 DAO 和 ServiceLocator
class 除非你最终为它创建一个 RequestContext
类型。
默认情况下,gwt 在获取对象时不附加集合实体。您需要在 rf 请求中使用 .with("ingredients") 。确保你的披萨中有 getIngredients 方法 class。 rf 请求上下文将使用它来获取成分。如果您从休眠之类的东西中获取它,您可能还需要确保打开了一个事务。这将确保 rf 上下文在检索比萨饼的成分时可以使用附加的实体。
请注意,您不想使用 with("getIngredients") rf 上下文将正确调用 get 方法。
context.get().with("ingredients").fire(new Receiver<>)