Несовместимость модификации объекта в Play Framework 2.2.X
Вот сделка:
public static List<Survey> getFilteredSurveys(Municipality municipality, Company company) {
String sql = "SELECT DISTINCT id FROM survey INNER JOIN " +
"(SELECT SURVEY_ID FROM publicity INNER JOIN brand "+
"ON publicity.brand_id=brand.id WHERE brand.company_id="+company.getId()+") "+
"ON survey_id=survey.id WHERE survey.municipality_id="+municipality.getId();
RawSql rawSql = RawSqlBuilder.parse(sql).create();
List<Survey> surveys = Ebean.find(Survey.class).setRawSql(rawSql).findList();
for (Survey survey : surveys) {
List<Publicity> publicities = new ArrayList<>();
for (Publicity publicity : survey.publicities) {
if(publicity.getBrand().getCompany() == company){
publicities.add(publicity);
}
}
survey.setPublicities(publicities);
}
return surveys;
}
Это приложение предназначено для измерения публичности в данном месте, поэтому люди загружают "Опрос" о месте, содержащем всю "Публичность", которая есть в этом месте.
Предполагается, что эта функция возвращает список, у каждого опроса есть список, а у каждой рекламной компании есть бренд, связанный с компанией (например, Coke -> Coca Cola Co.)
То, что я пытаюсь сделать, это следующее: для данной компании показать все опросы, содержащие "Coca Cola Co." реклама, но показывающая только рекламу, принадлежащую "Coca Cola Co."
У меня есть контроллер 'Surveys', который получает форму с муниципалитетом и компанией, вызывает этот метод, и он выводит представление с его результатом.
Это часть шаблона представления:
@(surveys: java.util.List[Survey])
@for(survey <- surveys){
@for(publicity <- survey.getPublicities){
<tr>
<td>@publicity.getBrand.getName</td>
<td>@publicity.getType.getName</td>
<td>@publicity.getSquareMeters</td>
</tr>
}
}
Проблема: хотя я удалил некоторые рекламные объявления из каждого опроса, все рекламные объявления отображаются в представлении. Почему это происходит? Я знаю, что я не сохраняю изменения, и я не хочу, я просто хочу временно скрыть данные, чтобы пользователь видел только рекламные материалы, принадлежащие данной компании. Почему этот вид не использует опросы в том виде, в каком они им даны, модифицированные?
2 ответа
На самом деле я поставлю это в ответ...
Вы должны посмотреть на SQL, выполненный в журнале (потому что я подозреваю, что вы получаете N+1) здесь, и вы могли бы довольно легко избежать этого.
Возможно, вам следует изменить исходный sql-код, чтобы он включал столбцы publicities в предложение select (name, type, squareMeters), чтобы избежать дополнительных запросов.
В качестве альтернативы вы можете добавить выборку ("publicities") к запросу (чтобы они охотно выбирались через соединение 100 запросов за раз).
Также обратитесь к: https://github.com/ebean-orm/avaje-ebeanorm/issues/223... RawSql, который включает в себя OneToMany не работает
https://github.com/ebean-orm/avaje-ebeanorm/issues/224... Улучшение добавления RawSqlBuilder.tableAliasMapping()
В идеале вы сможете использовать 4.5.2 и воспользоваться этим исправлением и этим улучшением.
Итак, я нашел исправление, Мое исправление было:
for (Survey survey : surveys) {
survey.getAddress(); //This line fixes the issue
List<Publicity> publicities = new ArrayList<>();
for (Publicity publicity : survey.publicities) {
if(publicity.getBrand().getCompany() != null){
if(publicity.getBrand().getCompany().getId().equals(company.getId())){
publicities.add(publicity);
}
}
}
survey.setPublicities(publicities);
}
Я предполагаю, что проблема заключается в том, как ebean лениво создает объекты, несмотря на установку Publicities в FetchType.EAGER
и тот факт, что выход из этой функции был ожидаемым, также проверяя surveys
в контроллере вроде бы нормально, а также @println(surveys)
в представлении показаны только рекламные объявления, соответствующие компании, которую я выбрал.