Тот же самый метод запроса Query;Может ли Springboot или Hibernate заблокировать запрос, если объект (не полностью) загружен в память? - PullRequest
0 голосов
/ 05 ноября 2019

Я надеюсь, что смогу прояснить ситуацию и разобраться в сути проблемы. Поэтому у меня есть приложение, в котором я использую Spring-boot и hibernate. Я использую JPA-репозиторий интерфейсов для DAO. У меня есть объект с именем NameSection, который содержится в 7 различных объектах. NameSection имеет 3 списка различных именных объектов (латинское имя, общее имя, шведское имя). Когда я вызываю мой сервис. GetNameSection (30);например, я получаю разные результаты в зависимости от того, где я это называю. Если я вызываю его из моего контроллера, где у меня есть неполная копия раздела имен, он, похоже, не хочет делать запрос к моей базе данных, даже если я вызываю мой сервис и getNameSection (nameSectionId);(который, в свою очередь, вызывает мои JPA-репозитории).

Возможно ли, что загрузка Spring или Hibernate остановит запрос к моей базе данных, потому что он имеет, как он считает, полный NameSection в своей памяти?

Метод, с которым я борюсь, вызывается, когда я в форме отправляю объект (скажем, Plant-object) и хочу перейти к связанной форме NameSection.

Когда я отправляю форму Plant, я получаю инъекцию растения моему методу в качестве модельного атрибута. В этом методе я получаю NameSection-id и вызываю service.getNameSection (nameSectionId);и это не дает мне полный раздел названия. В форме установки я ссылаюсь на раздел имен, поэтому в моем списке CommonName (в NameSection) у меня есть один загруженный CommonName. Но есть еще кое-что для сбора, поэтому я и вызываю свой сервис.

Я как бы сводил это к следующему: если я отправляю Plant-форму, которая содержит NameSection.id = 30, и я вызываю service.getNameSection (30);Я получу nameSection только с одним CommonName.

Если я отправлю другую Plant-форму, которая содержит другой NameSection, но я жестко закодировал service.getNameSection (30);и, в любом случае, зарегистрировав его, как тест, я получаю полный NameSection (30) и полностью загруженный список.

Что еще более неприятно, так это то, что NameSection работает так, как я хочу, для объекта типа Fish, который также содержитNameSection. Оба метода используют один и тот же поток. В методе, приведенном ниже, просто замените каждое «растение» на «рыбу», и это то же самое.

Я подозреваю, что весна или спящий режим или что-то требует сокращения. Я пытался обнулить Plant и NameSection перед вызовом service.getNameSection (id);также, но он не будет загружать полный nameSection, если у меня уже есть неполная копия, даже если она обнуляется. По крайней мере, так мне кажется. Я застрял на несколько дней.

Вызов service.getPlant (plantId);также загрузит полный NameSection, но это не работает ни в этом конкретном методе. Работает нормально в моем методе editPlant, например, в том же классе контроллера.

Итак, это метод:

// Process Plant form
@RequestMapping("/processPlantForm")
public String savePlantForm(Model model,
@RequestParam("saveButt") String saveButt,
// plant holds an incomplete namesection at this point
@Valid @ModelAttribute("plant") Plant plant, 
BindingResult theBindingResult){

...snipped validation...


plantService.savePlant(plant);

if (saveButt.equals("Edit NameSection")) {

   // Here is the problem section!!

NameSection nameSec = 
    plantService.getNameSection(plant.getNameSection().getId());
System.out.println("common names size: " + nameSec.getCommonNames().size());

   // Hardcoded test phrase         
   NameSection secNameSec = plantService.getNameSection(30);       
   System.out.println("common names size: " + secNameSec.getCommonNames().size());

model.addAttribute("plant", plant);
model.addAttribute("nameSectionForm", new NameSectionForm(nameSec));
model.addAttribute("inflateNameSection", true);
    return "form/create-plant";
}

else {      
    return "redirect:/listPlant";
}
}

Итак, перейдем к этому методу с растением, которое содержитNameSection с идентификатором 30 в обоих случаях «getNameSection ( id )» - вызывает загрузку NameSection (id = 30) только с одним CommonName (которое соответствует неполному NameSection из modelAttribute).

Переходя к этому методу с любым другим заводом, который НЕ содержит NameSection (id = 30), он загрузит полный NameSection (id = 30) со всеми связанными CommonNames в моей «Жестко закодированной тестовой фразе».

В обоих случаях я получу все шведские имена и все латинские имена, связанные с NameSection, вероятно потому, что они оба являются пустыми списками в неполном NameSection из ModelAttribute.

Итак, я ожидал, что plantService.getNameSection(nameSectionId);всегда давать один и тот же результат для одного и того же nameSectionId ofc. Но кажется, что какой-то «умный ярлык» заставляет его пропустить несколько шагов, если кусочки доступны в памяти, и что в этом случае он делает ложные предположения, или это только я?

Возможно, я мог бы создать специальный запрос для запроса отсутствующих CommonNames, но должен быть более аккуратный способ. И что меня убивает, так это то, что он работает 1 из 7 различных объектов, которые содержат раздел имен. Конечно, между ними должно быть какое-то различие, но я просто не могу его найти. Единственным различием, которое я обнаружил, было то, что у меня изначально была «Модель модели» после «BindingResult theBindingResult» при внедрении метода. Я переместил это, чтобы соответствовать рабочему методу для рыб, но это не делало никакого различия.

Я также попытался добавить вызов getCommonNames (). Size () в мой метод service.getNameSection (id) для "сбора Lazy-списка", но он не сделал различий.

AnyPro, кто получил представление о том, что случилось?

1 Ответ

0 голосов
/ 05 ноября 2019

Я не хотел создавать больше текстовой стены, чем я, но я подумал, что кто-то захочет увидеть упомянутый метод работающей рыбы.

    @RequestMapping("/processFishForm")
    public String processFishForm(Model model,
                            @RequestParam("saveButt") String saveButt,
                            @Valid @ModelAttribute("fish") Fish fish,           
                            BindingResult theBindingResult) {

    // this is the snipped validation from plant-method example above
    if (theBindingResult.hasErrors()) {
        System.out.println(theBindingResult.getAllErrors());
        return "form/create-fish";
    }

    fishService.saveFish(fish);

    if (saveButt.equals("Edit NameSection")) {
        NameSection nameSec = fishService.getNameSection(fish.getNameSection().getId());

        model.addAttribute("inflateNameSection", true);
        model.addAttribute("fish", fish);
        model.addAttribute("nameSectionForm", new NameSectionForm(nameSec););
        return "form/create-fish";
    } 
    else {
        return "redirect:/listFish";
    }
}

И FishService, и PlantService имеютточно такой же метод getNameSection (id) и они на 100% взаимозаменяемы согласно моим тестам.

Обновление Итак, я создал новый DAO (JpaRepository-interface)для CommonNames (поскольку у меня их нет) и создал пользовательский метод:

List<CommonName> findByNameSection(NameSection nameSection);

Затем в службе, когда я вызываю NameSection, служба также вызовет этот метод, чтобы убедиться, что я получаю все CommonNames. Теперь это работает так, как я хочу. За исключением того, что я, вероятно, делаю ненужный запрос к базе данных, чтобы исправить что-то еще.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...