2015-11-23 4 views
0

Я учу RequestFactory. У меня простой пример работы. Теперь я хотел бы реализовать для РФ этих субъектов снизу:RequestFactory Параметр Entity: List <OfOtherEntity> имеет значение null для клиента. На сервере нормально


пакет сервера

@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 класс для 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; 
} 

Shared пакет

Я написал 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<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(); 
} 

пакета Client

И вот так я получить данные из сервер:

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 классе в get() методы я печать на инфокоды об ингредиентах. На стороне сервера все работает.

Проблема в том, что когда я звоню p.getIngredients(), я получаю null, а не список IngredientsProxies.

Это происходит потому, что у меня нет классов Dao и Locator для Ingredients Entity?

Пожалуйста, помогите.

Ответ: Entity Отношения

Изменения связанных объектов могут быть сохранены в одном запросе. Например, этот код из примера примера DynatableRF в соединительной линии GWT создает новое лицо и адрес в одно и то же время:

PersonRequest context = requestFactory.personRequest(); AddressProxy address = context.create (AddressProxy.class); PersonProxy person = context.create (PersonProxy.class); человек.setAddress (адрес); context.persist() используя (человек) .fire (...); RequestFactory автоматически отправляет весь граф объекта в одном запросе. В этом случае реализация Person.persist() на сервере отвечает за сохранение связанного адреса также, который может или не может произойти автоматически, в зависимости от структуры ORM и того, как определяется связь. Обратите внимание, что RequestFactory в настоящее время не поддерживает внедренные объекты (@Embedded в различных структурах ORM), потому что он ожидает, что каждая сущность будет существовать независимо со своим собственным идентификатором.

При запросе сервера RequestFactory автоматически не заполняет отношения в графе объектов. Для этого используйте метод with() по запросу и укажите имя связанного свойства в виде строки:

Запрос findReq = requestFactory.personRequest(). Find (personId) .with ("address"); Также необходимо использовать метод with() для получения любых свойств с типами, расширяющими ValueProxy. Метод with() принимает несколько аргументов String, поэтому вы можете сразу указать несколько имен свойств. Чтобы указать вложенные свойства, используйте точечную нотацию. Собираем все вместе, вы можете иметь

Запрос findReq = найти (PersonId) .with ("телефон", "address.city", "address.zip")

ответ

1

По умолчанию gwt не связывает объекты коллекции при извлечении объекта. Вам нужно использовать .with («ингредиенты») по вашему RF-запросу. Убедитесь, что у вас есть метод getIngredients в классе pizza. Контекст запроса rf будет использовать это для извлечения ингредиентов. Вам также может потребоваться убедиться, что транзакция открыта, если вы извлекаете ее из чего-то вроде спящего режима. Это позволит убедиться, что rf-контекст может использовать прикрепленный объект при извлечении ингредиентов для вашей пиццы.

Обратите внимание, что вы не хотите использовать параметр with ("getIngredients"), то rf-контекст вызовет метод get правильно.

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

Может ли «ингредиенты» пройти каким-то образом сохранить? Я хотел бы избегать струн, сколько смогу :-) – masterdany88

+1

У меня было такое же чувство и на самом деле было предложено усилить добавление поддержки аннотаций @Eager к классу Proxy, чтобы идентифицировать коллекции, которые нужно получать с нетерпением. Я могу на самом деле сделать это сам в какой-то момент, но переключился на использование GWT-RESTY, чтобы мои api были более портативными. Я создал константы в прокси в качестве помощников, чтобы я мог использовать что-то вроде (PizzaProxy.Ingredients) вместо того, чтобы использовать строку и изменять ее в нескольких местах. Имейте в виду, что это значительное увеличение производительности, чтобы не отправлять коллекции по умолчанию. –

+0

Это можно сделать также с отражением или генерацией кода. Придется ждать, пока Google его выполнит. – masterdany88

2

По умолчанию RequestFactory не рекурсивно чтобы произошла выборка, чтобы сохранить как вызовы БД, так и пробел на проводе.

Если вам нужно имущество ingredients, вы должны запросить его. Вместо

context.get().to(... 

добавить вызов Request.with(String... propertyRefs) там, и указать, что вы хотите ингредиенты:

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

Не имеющий локатор для Ingredients типа может в конечном итоге mattering, но вы Если вы попытаетесь использовать эти объекты таким образом, чтобы были нужны либо Locator, либо статические методы в классе. Для этого вам не нужен определенный класс DAO и ServiceLocator, если вы не введете в него тип RequestContext.

+0

Может ли «ингредиенты» пройти каким-то образом сохранить? Я бы хотел избегать струн, сколько смогу :-) – masterdany88