Pobraniem kolekcji - Spring/Hibernate

Odpowiedz Nowy wątek
2014-11-24 14:32
eL
0

Cześć.
Używam: SpringMVC, Hibernate, MySQL.

Mam problem z pobraniem kolekcji z bazy danych.
Pobieram użytkownika który relacją wiele do wielu jest połączony z Rolami (admin, user itd).

Kiedy pobieram użytkownika przez serwis, na stronie nie pojawia się żaden błąd. Dopiero w debugerze wyrzuca coś takiego:
user image

Przewertowałem stackoverflow i wydaje mi się że sesja zostaje zamknięta zanim jeszcze zostanie pobrana lista ról.
Problem w tym że zrobiłem chyba wszystko co wyczytałem i dalej jest to samo.

Wkleję po kolei najważniejsze fragmenty.

Model klasy:

@Entity
@Table(name="PERSON")
public class Person {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id_person;
(reszta pól)
    @ManyToMany(fetch = FetchType.LAZY,cascade = CascadeType.ALL)
    @JoinTable(name = "PERSON_ROLES", joinColumns = {@JoinColumn (name = "PERSON_ID")},inverseJoinColumns = {@JoinColumn(name="ROLE_ID")})
    private Set<Role> personRole = new HashSet<Role>();

DAO:

@Repository
public class PersonDAOImpl implements PersonDAO {

    @Autowired
    private SessionFactory sessionFactory;

    public void setSessionFactory(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }
@SuppressWarnings("unchecked")
    public Person getPersonByEmail(String email) {
        List<Person> personList = new ArrayList<Person>();
Session session = this.sessionFactory.getCurrentSession();

personList = session.createQuery("from Person where email=?")
                .setParameter(0, email)
                .list();

        if (personList.size() > 0) {
            return personList.get(0);
        } else {
            return null;
        }

    }
}

Service:

@Service
public class PersonServiceImpl implements PersonService {

    @Autowired
    private PersonDAO personDAO;

    public void setPersonDAO(PersonDAO personDAO) {
        this.personDAO = personDAO;
    }
    @Override
    @Transactional
    public Person getPersonByEmail(String email) {
        return this.personDAO.getPersonByEmail(email);
    }

Controller:

 @RequestMapping(value = "/registerSchool", method = RequestMethod.POST)
    private ModelAndView registerSchoolSave(@Valid @ModelAttribute("school") School school, BindingResult result,HttpServletRequest request){
        ModelAndView modelAndView = new ModelAndView();

        if(result.hasErrors()){
            modelAndView.setViewName("register/registerSchool");
            return  modelAndView;
        }
        Principal principal = request.getUserPrincipal();

        Person person = personService.getPersonByEmail(principal.getName());

        modelAndView.setViewName("register/registerSchoolSuccess");
        return modelAndView;
    }

front controller:

 <bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
        <property name="sessionFactory" ref="hibernate4AnnotatedSessionFactory" />
    </bean>

    <tx:annotation-driven transaction-manager="transactionManager"/>

    <bean id="personDAO" class="pl.lbednarski.edziennik.dao.PersonDAOImpl">
        <property name="sessionFactory" ref="hibernate4AnnotatedSessionFactory"/>
    </bean>

    <bean id="personService" class="pl.lbednarski.edziennik.service.PersonServiceImpl">
        <property name="personDAO" ref="personDAO"/>
    </bean>

Połączenie z bazą jest ponieważ pobiera wszystkie pola oprócz kolekcji.

Ktoś ma pomysł albo widzi błąd?

Pozdrawiam
~eL

edytowany 2x, ostatnio: eL, 2014-11-24 14:36
na szybko: spróbuj dac FetchType.EAGER zamiast LAZY - azalut 2014-11-24 14:40

Pozostało 580 znaków

2014-11-24 15:07
0

spróbuj zmodyfikować getPersonByEmail na:

public Person getPersonByEmail(String email) {
       Session session = sessionFactory.getCurrentSession();  //albo sessionFactory.openSession();
       Query query = session.createQuery("from Person where email=?").setParameter(0, email);
       List<Person> personList = query.list();

        if (personList != null) {
            return personList.get(0);
        }
        return null;
    }
edytowany 3x, ostatnio: azalut, 2014-11-24 15:08
Rozumiesz dlaczego tak się dzieje? - NoZi 2014-11-24 16:19
tak mniej-więcej :P ale próbuje się dowiedzieć tak więcej niż mniej - azalut 2014-11-24 20:03

Pozostało 580 znaków

2014-11-24 16:14

Twój problem polega na tym, że próbujesz się dostać poza transakcją do danych których nie ma. Aby temu zaradzić masz kilka opcji.

  1. Zmienić na FetchType.EAGER przy kolekcji którą chcesz wyciągnać.
  2. Zrobić FETCH JOIN'a
  3. Wyciągnąć dane w transakcji, które będą Ci później potrzebne

Taka uwaga na boku, jeśli tylko pobierasz dane to oznacz metodę/serwis @Transactional(readOnly = ture). Wtedy dostawca może ale nie musi zoptymalizować pewne rzeczy(to jest tylko hint).


Hate the sin, love the sinner
edytowany 2x, ostatnio: NoZi, 2014-11-24 16:17

Pozostało 580 znaków

2014-11-25 16:05
eL
0

Zamiana Fetch na Eager pomogła ;) Dzięki!

edytowany 1x, ostatnio: eL, 2014-11-25 16:05

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0