Каждый раз, когда Spring MVC Controller возвращает пожар ModelAndView Hibernate, выбирается - PullRequest
0 голосов
/ 14 октября 2018

У меня есть небольшое веб-приложение на основе Spring MVC и Hibernate.Мой пользовательский объект имеет отношение oneToMany с Pet, object:

@OneToMany(mappedBy="user", cascade=CascadeType.ALL, fetch=FetchType.EAGER)
private Set<Pet> myPets;

Даже я сохраняю свой пользовательский объект в сеансе после входа в систему (я знаю, это грех), и в него включаются его домашние животные, каждый разметод Controller вызывается, после того, как он возвращает объект ModelAndView, в журналах показывается выбор режима гибернации.

Например,

@RequestMapping(value = "/in_pet-see", method = RequestMethod.GET)
public ModelAndView getSee(@RequestParam("pid") Integer pId, ModelAndView model) {
    User u = getUserFromSession();
    if(u==null) {
        u = getUser();
    }
    Set<Pet> pets = u.getMyPets();
    Pet p = getPetFromSet(pets, pId);
    model.addObject("user", u);

    model.addObject("petType", petTypeMap.get(p.getType()));
    model.addObject("petAttribute", p);
    model.setViewName("b-see-pet");
    return model;
}

private User getUserFromSession() {
    return (User)session().getAttribute("user");
}

public static HttpSession session() {
    ServletRequestAttributes attr = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
    return attr.getRequest().getSession(true); // true == allow create
}


private Pet getPetFromSet(Set<Pet> set, int pId) {
    Pet myPet = null;
    for (Iterator<Pet> it = set.iterator(); it.hasNext(); ) {
        Pet p = it.next();
        if (p.getPetId()==pId) {
            myPet = p;
        }
        System.out.println("Pet found");

    }
    return myPet;
}

Как этого избежать?

ПРИМЕЧАНИЕ

Мой способ исправить это - клонировать спящий объект и поместить клона.в HttpSession, затем в тех методах, которые могут вносить изменения (редко встречающиеся в моем приложении) в зависимые объекты пользователя или пользователя, в конце этого метода вызывается метод синхронизма:

/** Get a new user from DDBB, after some change and put it on Session to deliver fresh data */
private void sinchronizeUser() {
    User oldSmith = getUserFromSession();
    User u = myUserService.loadUserById(oldSmith.getUserId());
    User smith = (User) u.clone();
    session().setAttribute("user", smith);
}

1 Ответ

0 голосов
/ 16 октября 2018

Полагаю, такое поведение является следствием так называемого механизма грязной проверки Hibernate.Здесь вы можете узнать больше об этом:

https://vladmihalcea.com/the-anatomy-of-hibernate-dirty-checking/

В моем случае я, наконец, нашел способ предотвратить выбор Hibernate, и это просто клонирование объекта Hibernate и использование клона в моемHttpSession.Я имею в виду, что я все еще использую fetch eager, потому что мне нужно предварительно загрузить все пользовательские данные (которые являются небольшими).А использование объекта-клона hibernate не приводит к обновлению.

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