Grails i klasy domenowe o tych samych nazwach
W komentarzach do notatki Jacka Laskowskiego został poruszony temat dwóch klas domenowych o tych samych nazwach, ale w różnych pakietach.
Jak sobie radzi z tym GORM? Nie wykrywa różnicy.
Na początku utworzyłem dwie klasy domenowe o tej samej nazwie, ale w różnych pakietach. Nie umieściłem w nich żadnych właściwości. Uruchamiam projekt i widzę, że została utworzona jedna tabelka.
Dodałem do kontrolera utworzenie instancji obu klas i zapis do bazy. Zapisało oba rekordy do tej samej tabeli.
Kolejna zmiana w klasach domenowych to dodanie właściowości, innych dla obu klas. Efekt? Jedna tabelka ze wszystkimi właściwościami. Tylko, że tym razem już zapis nie działa. Wygenerowana tabelka posiada pola "not null" bez domyślnych wartości (MySQL). Tak więc zapisanie rekordu do bazy nie powodzi się, gdyż w zależności od tego, którą instancję zapisujemy brakuje nam jakiegoś pola: "Field 'abc' doesn't have a default value".
Skoro możemy robić klasy w pakietach, żeby uniknąc konfliktów nazw, to szkoda, że nie jest to również załatwione na poziomie GORM.
Rzeczywiście, głupio to wygląda. O ile samo wskazanie na inną tabelę w GORM da się jakoś ustawić za pomocą statycznego domknięcia ‘mapping’, o tyle „automaty” w grails głupieją przy np. generowaniu kontrolerów – dla różnych klas dziedzinowych, w różnych pakietach, wygenerowane zostają różne kontrolery w pakietach analogicznych, jednak „pada” tu mapowanie URLi. Generowanie widoków to już porażka całkowita, bo po prostu wzajemnie się nadpisują.
Tak sobie myślę (wyspałem się, to sobie myślę
), że tak musi być po prostu. GORM to Hibernate, a więc dwie encje JPA (poziom Hibernate) o tych samych nazwach również trafią na tą samą tabelę. Wystarczy więc skorzystać z static mapping, a tam table, aby tabele zmienić. Podobnie jak w JPA – @Table.
Tak, zgadza się, macie całkowitą rację, można to przemapować. Ale czy na pewno nie dało by się tego obsłużyć na poziomie GORM? Skoro mamy pakiety w klasach, to dlaczego mapowanie sobie z tym nie radzi?
A co jeśli napiszemy dwa moduły korzystające z tej samej bazy i trafimy na konflikt nazw? Albo po prostu będziemy chcieli uruchomić dwa moduły, w których są klasy domenowe o takich samych nazwach? Trzeba będzie jeden z nich zmienić :/