Po korzystaniu z Hibernacji w większości moich projektów przez około 8 lat, znalazłem się w firmie, która zniechęca do jego używania i chce, aby aplikacje współdziałały z bazą danych tylko za pomocą procedur przechowywanych.
Po zrobieniu tego przez kilka tygodni nie byłem w stanie stworzyć bogatego modelu domenowego aplikacji, którą zaczynam budować, a aplikacja wygląda jak (okropny) skrypt transakcyjny.
Niektóre z problemów, które znalazłem, to:
- Nie można nawigować po wykresie obiektowym, ponieważ procedury przechowywane po prostu ładują minimalną ilość danych, co oznacza, że czasami mamy podobne obiekty z różnymi polami. Jeden przykład to: mamy procedurę składowaną do pobierania wszystkich danych od klienta, a drugą do pobierania informacji o koncie plus kilka pól od klienta.
- Wiele logiki kończy się na klasach pomocniczych, więc kod staje się bardziej uporządkowany (z jednostkami używanymi jako stare struktury C).
- Bardziej nudny kod rusztowania, ponieważ nie ma frameworku, który wyodrębniałby zestawy wyników z procedury składowanej i umieszczałby ją w encji.
Moje pytania to:
- czy ktoś był w podobnej sytuacji i nie zgodził się z podejściem do procedury sklepu? co zrobiłeś?
- Czy istnieje faktyczna korzyść ze stosowania procedur przechowywanych? oprócz głupiego punktu „nikt nie może wydać tabeli upuszczania”.
- Czy istnieje sposób na utworzenie bogatej domeny przy użyciu procedur przechowywanych? Wiem, że istnieje możliwość użycia AOP do wstrzykiwania DAO / repozytoriów do bytów, aby móc poruszać się po grafie obiektowym. Nie podoba mi się ta opcja, ponieważ jest bardzo bliska voodoo.
Wniosek
Po pierwsze, dziękuję wszystkim za odpowiedzi. Doszedłem do wniosku, że ORM nie pozwalają na tworzenie modeli Rich Domain (jak niektórzy wspominali), ale upraszcza to (często powtarzalne) prace. Poniżej znajduje się bardziej szczegółowe wyjaśnienie wniosku, ale nie jest ono oparte na żadnych twardych danych.
Większość aplikacji żąda i wysyła informacje do innych systemów. Aby to zrobić, tworzymy abstrakcję w terminach modelu (np. Zdarzenie biznesowe), a model domeny wysyła lub odbiera zdarzenie. Wydarzenie zwykle wymaga niewielkiego podzbioru informacji z modelu, ale nie całego modelu. Na przykład w sklepie internetowym bramka płatności żąda pewnych informacji o użytkowniku i kwoty całkowitej, aby obciążyć użytkownika, ale nie wymaga historii zakupów, dostępnych produktów i całej bazy klientów. Wydarzenie ma więc mały i konkretny zestaw danych.
Jeśli weźmiemy bazę danych aplikacji jako system zewnętrzny, musimy stworzyć abstrakcję, która pozwoli nam zmapować jednostki Modelu Domeny do bazy danych ( jak wspomniał NimChimpsky , używając mapera danych). Oczywista różnica polega na tym, że teraz musimy ręcznie opracować mapowanie dla każdej encji modelu do bazy danych (starszego schematu lub procedur przechowywanych), z tym dodatkowym utrudnieniem, że skoro nie są one zsynchronizowane, jedna encja domeny może częściowo mapować do encji bazy danych (np. klasa UserCredentials, która zawiera tylko nazwę użytkownika i hasło, jest mapowana na tabelę użytkowników, która ma inne kolumny), lub jedna encja modelu domeny może być mapowana na więcej niż jedną encję bazy danych (na przykład, jeśli istnieje relacja jeden do jednego jedno mapowanie na stole, ale chcemy wszystkich danych w jednej klasie).
W aplikacji z kilkoma jednostkami dodatkowa praca może być niewielka, jeśli nie ma potrzeby poprzecznego przekształcania jednostek, ale zwiększa się, gdy istnieje warunkowa potrzeba poprzecznego przenoszenia jednostek (i dlatego możemy chcieć zaimplementować jakiś rodzaj „leniwego” Ładuję'). W miarę, jak aplikacja ma coraz więcej encji, ta praca po prostu się zwiększa (i mam wrażenie, że rośnie nieliniowo). Zakładam tutaj, że nie próbujemy wynaleźć ORM.
Jedną z korzyści traktowania DB jako systemu zewnętrznego jest to, że możemy kodować sytuacje, w których chcemy uruchomić 2 różne wersje aplikacji, w których każda aplikacja ma inne mapowanie. Staje się to bardziej interesujące w scenariuszu ciągłych dostaw do produkcji ... ale myślę, że jest to również możliwe w przypadku ORM w mniejszym stopniu.
Odrzucę aspekt bezpieczeństwa, ponieważ programista, nawet jeśli nie ma dostępu do bazy danych, może uzyskać większość, jeśli nie wszystkie informacje przechowywane w systemie, po prostu wstrzykując złośliwy kod (np. Nie mogę uwierzyć, że zapomniałem usunąć wiersz rejestrujący dane karty kredytowej klientów, drogi panie! ).
Mała aktualizacja (6/6/2012)
Procedury przechowywane (przynajmniej w Oracle) zapobiegają robieniu czegoś takiego jak ciągłe dostarczanie z zerowym przestojem, ponieważ każda zmiana struktury tabel spowoduje unieważnienie procedur i wyzwalaczy. Dlatego podczas aktualizacji bazy danych aplikacja również nie działa. Oracle zapewnia rozwiązanie dla tego zwanego Redefinition opartym na edycji , ale kilka DBA, o które pytałem o tę funkcję, wspomniało, że była ona słabo zaimplementowana i nie umieściłaby jej w produkcyjnym DB.
Odpowiedzi:
Twoja aplikacja powinna być nadal modelowana na podstawie zasad projektowania opartych na domenie. Niezależnie od tego, czy używasz ORM, zwykłego JDBC, wywoływanie SP (lub cokolwiek innego) nie powinno mieć znaczenia . Mamy nadzieję, że cienka warstwa oddzielająca twój model od SP powinna załatwić sprawę w tym przypadku. Jak stwierdzono w innym plakacie , powinieneś zobaczyć SP i ich wyniki jako usługę i zmapować wyniki do modelu domeny.
źródło
W świecie finansów (i miejscach, w których wymagana jest zgodność z Sarbanes-Oxley ), musisz mieć możliwość kontrolowania systemów, aby upewnić się, że robią to, co powinny. W takich przypadkach o wiele łatwiej jest zapewnić zgodność, gdy cały dostęp do danych odbywa się za pomocą procedur przechowywanych. A po usunięciu całego ad-hoc SQL znacznie trudniej jest ukryć różne rzeczy. Na przykład, dlaczego byłoby to „dobre”, odsyłam do klasycznego artykułu Kena Thompsona Refleksje na temat Trusting Trust .
źródło
Procedury przechowywane są znacznie bardziej wydajne niż kod SQL po stronie klienta. Wstępnie kompilują SQL w bazie danych, co pozwala mu również przeprowadzać optymalizacje.
Architektonicznie SP zwróci minimalną ilość danych wymaganych dla zadania, co jest dobre, ponieważ oznacza, że przesyłanych jest mniej danych. Jeśli masz taką architekturę, musisz pomyśleć o DB jako o usłudze (pomyśl o tym jako o usłudze sieciowej, a każdy SP jest metodą wywoływania). Praca z nim w ten sposób nie powinna stanowić problemu, podczas gdy ORM poprowadzi cię do pracy ze zdalnymi danymi tak, jakby były lokalne, w ten sposób nakłaniając do wprowadzenia problemów z wydajnością, jeśli nie będziesz ostrożny.
Byłem w sytuacjach, w których całkowicie korzystaliśmy z SP, DB dostarczyło API danych i korzystaliśmy z niego. Ta konkretna aplikacja była bardzo duża i działała niesamowicie dobrze. Po tym nie będę miał nic złego do powiedzenia na temat SP!
Jest jeszcze jedna zaleta - DBA napiszą dla ciebie wszystkie zapytania SQL i z przyjemnością obsłużą całą hierarchię relacyjną w DB, więc nie musisz.
źródło
the approach of letting the DBAs write the procedures smells like development silos
+100 internetów do ciebie za ten klejnot prawdy. Zawsze widziałem to jako przypadek, w którym dostęp do danych był kontrolowany za pomocą procedur przechowywanych.Często zdarza się, że programiści nieprawidłowo używają swoich obiektów ORM jako modeli domen.
Jest to niepoprawne i wiąże domenę bezpośrednio ze schematem bazy danych.
To, co naprawdę powinno mieć, to oddzielne modele domen tak bogate, jak chcesz i osobno używaj warstwy ORM.
Oznacza to, że będziesz potrzebować mapowania między każdym zestawem obiektów.
źródło
Obiekty domeny można zapełnić w dowolny sposób, nie jest konieczne używanie Hibernacji. Myślę, że właściwym terminem jest mapowanie danych . Bardzo możliwe, że utrwalone dane będą miały zupełnie inną strukturę niż obiekty domeny.
źródło