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.