myślę, że robią coś złego w swojej klasie DAO, ponieważ jesteś otwarta sesja i transakcji wewnątrz metody i prawdopodobnie wewnątrz każdej z metod w DAO.
Takie postępowanie wiąże się z wysokimi kosztami, a koncepcja jest zła, dlatego transakcja musi pogrupować zestaw operacji, który zakończy się sukcesem lub porażką. W większości przypadków transakcja bazy danych będzie powiązana z całą operacją biznesową, w tym przypadku z żądaniem REST. Coś jak
POST/user
@ RestController.createUser
otwarta transakcja
UserDAO.saveUser
popełnić transakcja
odpowiedź
Ponadto, jeśli spojrzysz na swój kod, otwierasz transakcję, a następnie zamykasz.
tx = session.getTransaction();
session.beginTransaction();
tx.commit();
W tym przypadku użytkownik wysyła zapytanie do bazy danych, więc transakcja nie jest wcale potrzebna.
Transakcje stanowią problem przekrojowy w Twojej aplikacji, a biorąc pod uwagę, że już używasz Springa, powinieneś spojrzeć na adnotację @Transactional (lub jego odpowiednik xml), aby uzyskać transakcyjność z AOP (Spring tworzy aroud aspect). Dzięki temu twój kod stanie się bardziej czytelny i łatwiejszy w utrzymaniu.
Odpowiedź @ManojP ma dobrą i złą rzecz. Myślę, że powinieneś unikać dwukierunkowych relacji, kiedy tylko możesz, bo to sprawia, że projekt jest trudniejszy. Moja rada jest taka: zaczynaj zawsze z jednokierunkowymi relacjami i jeśli znalazłeś przypadek, w którym nie możesz tego uniknąć, użyj go.Dobrą rzeczą jest to, że pokazuje wam użycie lazyness gdy robi:
List<User> users = profession.getUsers();
Ta linia kodu powinna być poza DAO. Co się dzieje, to, że masz listę użytkowników oznaczonych jako leniwi (jest to ustawienie domyślne), a następnie, po pobraniu zawodów z zapytaniem o kryterium, uruchamiany jest wybór ponad zawodami ze stołu, a każdy z obiektów Zawodu jest skonstruowany z kolekcja proxy zamiast prawdziwej kolekcji. Gdy wywołujemy metodę profession.getUsers(), nowy selektor jest przesuwany nad tabelą użytkowników, gdzie profession_id = profession.getId(). A więc:
- Lista wyników = kryteria.list();
- Wybierz * z zawodu
- professionA.getUsers();
- select * from Użytkownika gdzie profession_id =: professionA.getId()
Ale uwaga! jeśli masz zbiór zawodów (jak sądzę masz bo jesteś powrocie listy) i iteracyjne nad każdego zawodu i poprosić o listę użytkowników chcesz robić:
- wyników list = criteria.list();
- select * from Zawód
- dla każdego zawodu -> profession.getUsers
- select * from Użytkownika gdzie profession_id =: professionA.getId()
- select * from Użytkownika gdzie profession_id =: professionB.getId()
To będzie źle działać.
Odpowiedź @farvilain jest dobra. Ale w tym przypadku zawsze będziesz pobierał Zawód z tą kolekcją Użytkowników, ponieważ w twoim DAO zawsze używasz FetchMode.JOIN, a wtedy tracisz korzyści z lenistwa. Tak więc, jeśli zawsze chcesz mieć listę użytkowników, gdy pytasz o zawody, użyj lazy = true dla kolekcji użytkowników, ale pamiętaj o kosztach, jakie mogą mieć (jeśli użytkownik ma niezaplanowaną kolekcję A, gdy pytasz o zawody otrzymasz także listę użytkowników plus kolekcję A). Jeśli nie chcesz tego, to może mieć to sygnatura:
public List<Profession> getProfessionById(Long id, FetchMode fetchMode) throws Exception
To nie jest bardzo ładne, ale pokazuje, że klient DAO mógł wybrać tryb fecth.
Kryteria cr = session.createCriteria (User.class); cr.add (Restrictions.eq ("pid", pid)); List results = cr.list(); Czy mógłbyś również zaktualizować pytanie za pomocą mapowania i relacji ER między zawodem a użytkownikiem? Uważam, że mapowanie ManyToMany w tym przypadku można użyć EAGER FETCH w samym kodzie, a otrzymacie bezpośrednio obiekt Users in Profession. – pratikpawar
Czy możesz wyjaśnić w tym przypadku, jaka jest prośba o REST? – gabrielgiussi
Czy odpowiesz na kontrolę. – ozgur