Łukasz Kukawski

Łukasz Kukawski Deweloper aplikacji
internetowych

Temat: Hibernate, Spring, ManyToMany i problem z FetchType.LAZY

Nie wiem czy w tej grupie jeszcze ktoś odpowiada bo widzę że ostatni temat był w tamtym roku, ale co mi tam, mam problem, mam pytanie

Mam trzy encje:<br />
1)Artykuł<br />
2)Sklep<br />
3)Strona<br />

Relację między encjami:

Jeden artykuł może mieć wiele sklepów, jeden sklep może mieć wiele artykułów.<br />
Jeden artykuł może mieć jedną stronę.<br />
Jeden sklep może mieć jedną stronę.<br />

Jak to wygląda w kodzie:

Artykuł:

@OneToOne(fetch=FetchType.LAZY)
@Cascade({CascadeType.DELETE, CascadeType.DELETE_ORPHAN})
@JoinColumn(name = "strona_id")
private Strona strona;

@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(
name="sklep_artykul",
joinColumns=@JoinColumn(name="artykul_id"),
inverseJoinColumns=@JoinColumn(name="sklep_id")
)
private Set<Sklep> sklepy = new HashSet<Sklep>();

Sklep:

@OneToOne( fetch=FetchType.LAZY)
@Cascade({CascadeType.DELETE, CascadeType.DELETE_ORPHAN})
@JoinColumn(name = "strona_id")
private Strona strona;

@ManyToMany(mappedBy="sklepy", fetch=FetchType.LAZY)
private Set<Artykul> artykuly = new HashSet<Artykul>();

Podczas dodawania artykułu udostępniam możliwość podpięcia kilku sklepów poprzez listę select multiple.


form:select path="sklepy" multiple
items="${sklepy}" itemLabel="nazwa" itemValue="id"

W kontrolerze który wywołuję widok z dodaniem artykułu dodaję initBInder aby odwzorować Stringa z formularza na listę sklepów:

@InitBinder
protected void initBinder(HttpServletRequest request,
ServletRequestDataBinder binder) {
binder.registerCustomEditor(Set.class, "sklepy",
new CustomCollectionEditor(Set.class) {
@Override
protected Object convertElement(Object element) {
if (element != null) {
return sklepService.pobierzSklep(Integer
.parseInt(element.toString()));
}
return null;
}
});

Wszystko działa poprawnie po za jedną rzeczą.
Problem polega na tym że gdy generuję formularz z listą sklepów do wybrania, to hibernate generuję dodatkowe zbędne zapytania dla każdego sklepu, zaciągając powiązaną stronę.<br />
W tej sytuacji potrzebuję tylko nazwę oraz id sklepu, nic więcej nie potrzebuję.<br />
Gdy wygeneruję Select list pomijając atrybut path="sklepy" dodatkowe zapytania się nie generują.
Gdzie jest problem?
Adam Lesiak

Adam Lesiak Web developer - JEE
/ jQuery

Temat: Hibernate, Spring, ManyToMany i problem z FetchType.LAZY

Dzieje się tak dlatego, że dodałeś fetch=FetchType.LAZY do relacji @OneToOne. W tej relacji pobranie listy obiektów musi załadować obiekty relacyjne 1 do 1 gdyż są one związane jakby "na sztywno". Standardowo, bez FetchType.LAZY obiekty pobierane są poprzez JOIN, natomiast gdy dodasz FetchType.LAZY każdy obiekt w relacji 1 do 1 musi zostać doładowany poprzez równoległe zapytanie, stąd dodatkowe selecty.

Jest pewne rozwiązanie - optional=false. W encji Artykuł mamy zatem:

@OneToOne(fetch=FetchType.LAZY, optional=false)
(...)
private Strona strona;

Strony nie zostaną wtedy pobrane. Jednak osobiście rekomendowałbym ładowanie pełnych obiektów w relacjach @OneToOne, gdyż optional=false szerzej nie stosowałem.

Szeroka dyskusja na ten temat:
http://stackoverflow.com/questions/17987638/hibernate-...

Następna dyskusja:

Spring + hibernate - proble...




Wyślij zaproszenie do