26 stycznia 2009

Dlaczego nie warto trzymać transakcji w metodach klasy DAO

Wzorzec Data Access Object zwany w skrócie DAO jest wzorcem projektowym związanym z warstwą integracji. Klasa DAO zawiera metody odwołujące się do tzw. data storage, którym jest zazwyczaj baza danych. Wyobraźmy sobie sytuację, że musimy dokonać podmiany danych użytkownika, gdyż zmienił się jego adres zamieszkania. Procedura działania jest następująca:
1. Odszukanie użytkownika na podstawie jakiegoś identyfikatora
2. Pobranie adresu użytkownika
3. Ustawienie nowego adresu i zapisanie zmian do bazy danych
Każdy z tych punktów możemy traktować jako wywołanie pojedynczej metody obiektu (lub tez obiektów DAO). W standardowych przypadkach byłoby nierozsądnym otwieranie i zamykanie transakcji dla każdej z tych metod z osobna, gdyż niepotrzebnie zwiększałoby to wykorzystanie zasobów. Dodatkowo niepowodzenie jednego z trzech punktów powinno spowodować powrót bazy do stanu przed rozpoczęciem procesu uaktualniania adresu użytkownika. Rozwiązaniem nowej klasy zawierającej metodę w ramach, której wywoływane są poszczególne metody obiektu DAO. Dopiero tutaj, na początku tejże nowej metody otwieramy transakcję, która zamykana jest po wywołaniu ostatniej metody obiektu DAO. Czyli metody zapisującej nowy adres do bazy danych. W ten oto sposób popełniliśmy niechcąco wzorzec Application Service.

23 stycznia 2009

Moje prywatne żale

Dzisiaj nie będę oryginalny. Takie lamenty przewijają się co jakiś czas na forach internetowych związanych z Javą...

Od dłuższego czasu zabieram się za poznanie języka Ruby. W tym celu nabyłem nawet stosowną książkę, a tu się nagle okazuje, że jest coś takiego jak Scala, że niby to jest lepsze i z Javą powiązane. To ja się pytam kiedy na to wszystko znaleźć czas?

22 stycznia 2009

Moje wrażenia podczas obcowania z EMF, GMF, GEF

Ostatnio jestem zaangażowany w projekt zbudowany z niezależnych pluginów Eclipse’a. Taki system pozwalający na tworzenie modeli w oparciu o zdefiniowany, własny DSL. Dla osób nie siedzących w tym temacie dodam, iż wygląda to trochę jak edytor UML. Technologie użyte przy budowie systemu to EMF, GMF, GEF. Muszę przyznać, że czas wejścia w te technologie jest stosunkowo długi (przynajmniej jak dla mnie). Jednak, gdy już posiądzie się „tajemną” wiedzę tworzenie kompleksowych aplikacji staje się dużo prostsze. Kontakt ze stosunkowo prostą aplikacją zbudowaną o wspomniane frameworki powoduje, iż użytkownik końcowy ma wrażenie, że jest ona graficznie i funkcjonalnie dopieszczona. Nie trzeba zajmować się wieloma aspektami wymaganymi przy tworzeniu standardowych aplikacji takimi jak np. standardowe menu, integracja z repozytorium, przechwytywanie zmian w modelu od ostatniego zapisu, lokalizacja itp. Dużo rzeczy programowana jest poprzez model deklaratywny na podstawie, którego automatycznie generowany jest kod. W temacie EMF, GMF, GEF wciąż raczkuję. Może dlatego, iż rdzeń aplikacji tworzony jest przez mojego przełożonego, który dość długo siedzi w tym temacie, a moja rola ogranicza się głównie do poprawy zgłaszanych błędów. Jednakże jest to ciekawe dla mnie doświadczenie, gdyż sam widzę jak w przeciągu ostatnich dziesięciu lat zmienia się sposób pisania kodu i tworzenia systemów informatycznych.

21 stycznia 2009

Pętle i etykiety

Witam po dłuższej przerwie, ale do rzeczy. Czasami zdarza się (szczególnie w pracy), iż ktoś zagląda na mój kod. Często w takich momentach widzę zdziwienie na twarzy podglądacza, gdy zauważa, że używam etykiet dla zagnieżdżonych pętli. Wydaje mi się, że często pomija się to dobrodziejstwo, a szkoda.

loop: for (Connection connection : outcomingConnections) {
...
}

21 kwietnia 2007

Struktura drzewiasta i funkcja connectby (PostgreSQL)

Prędzej czy później większość z nas stanie przed koniecznością przechowywania danych w strukturze drzewiastej. W sieci istnieje wiele przykładów obrazujących to zagadnienie. Poniższy opis ma na celu pokazanie jednego ze sposobów „wyciagania” danych przechowywanych w tejże strukturze za pomocą funkcji connectby. Przykładem struktury drzewiastej jest tzw. adjacency list model:

CREATE TABLE wypowiedz_tab (
id_wypowiedzi bigint NOT NULL,
temat character varying(255),
tresc character varying(255),
id_ojca_wypowiedzi bigint
);

ALTER TABLE ONLY wypowiedz_tab
ADD CONSTRAINT wypowiedz_tab_pkey PRIMARY KEY (id_wypowiedzi);

ALTER TABLE ONLY wypowiedz_tab
ADD CONSTRAINT wypowiedz_tab_fkey FOREIGN KEY (id_ojca_wypowiedzi) REFERENCES wypowiedz_tab(id_wypowiedzi);

Powyższa tabela zawiera wypowiedzi umieszczane na grupie dyskusyjnej. Jeśli id_ojca_wypowiedzi posiada wartość różną od null znaczy to, iż wypowiedź ta jest odpowiedzią . W innym wypadku mamy do czynienia z wypowiedzią rozpoczynającą nową dyskusję.

Po zapełnieniu tabeli danymi chcielibyśmy w łatwy sposób pobierać dane bez względu na jakim znajdujemy sie poziomie w hierarchii naszego drzewa. Serwer baz danych PostgreSQL oferuje do tego zadania gotową funkcję connectby, znajdującą się w pliku share\contrib\tablefunc.sql. Składnia funkcji jest nastepująca:

connectby('nazwa_tabeli','nazwa_pola_PK','nazwa_pola_FK', 'wartość_pola_PK' , głębokość)


gdzie głębokość oznacza głębokość przeszukiwania.

W przypadku gdy argument 'głębokość' ma wartość 0, oznacza to, iż zostanie zwrócony rekord od którego rozpoczęto przeszukiwanie oraz wszystkie względem niego rekordy potomne.

Przed przejściem do następnego etapu należy utworzyć funkcję:

CREATE OR REPLACE FUNCTION connectby(text,text,text,text,int)
RETURNS setof record
AS '$libdir/tablefunc','connectby_text'
LANGUAGE C STABLE STRICT;

Przykład zapytania realizującego pobieranie danych za pomocą funkcji connectby:

SELECT * FROM connectby('wypowiedz_tab','id_wypowiedzi','id_ojca_wypowiedzi', '2',0) AS t(keyid bigint, parent_keyid bigint, level int);

Należy zaznaczyć, iż typy keyid i parent_keyid nie mogą się różnić. W powyższym przypadku jest to bigint. Dla tabeli, gdzie wartości klucza głwównego i klucza obcego byłyby tekstem zapytanie wyglądałoby następująco:

SELECT * FROM connectby('wypowiedz_tab','id_wypowiedzi','id_ojca_wypowiedzi', '2',0) AS t(keyid text, parent_keyid text, level int);

Jeśli interesuje nas zwrócenie w wyniku wszystkich kolumn naszej tabeli należy użyć złączenia:

SELECT tt.* FROM connectby('wypowiedz_tab','id_wypowiedzi','id_ojca_wypowiedzi', '2',0) AS t(keyid text, parent_keyid text, level int), wypowiedz_tab as tt where t.keyid=tt.id_wypowiedzi;

W katalogu doc\contrib\README.tablefunc serwera PostgreSQL znajduje się dokładniejszy opis funkcji connectby uwzględniający uzyskanie dodatkowej funkcjonalności, takiej jak np. sortowanie rekordów potomnych.

23 marca 2007

I love Hibernate...

Mówić w tym wypadku o miłości to trochę za szybko, ale z pewnością jest to zauroczenie. Po zapoznaniu się z tym szkieletem zastanawiam się jak to było możliwe, że przez tak długi czas pisałem aplikacje używając gołego JDBC? Widocznie wcześniej musiałem doświadczyć EJB 2.1, żeby teraz jeszcze bardziej docenić ten framework. Jak to mój kolega ujął: „Hibernate powinien być obowiązkowym wykładem obok fizyki i matematyki”. [no chyba trochę przesadził ;]

12 marca 2007

W życiu nie może być za łatwo

Po bojach z dokumentacją Hibernate'a przyszedł czas na konfigurację IDE ( w moim wypadku Eclipse). Procedura w tym wypadku jest standardowa:
  1. Znajdź odpowiedni plugin.
  2. Zainstaluj go.
  3. Znajdź przyczynę dlaczego plugin nie działa.
Tak też było i tym razem. Pełen entuzjazmu zasiadłem do swojej maszyny, aby zassać Hibernate Tools. Po pomyślnej instalacji zrestartowałem środowisko w celu sprawdzenia poprawności instalacji. Na pierwszy rzut oka wszystko wyglądało poprawnie. Skuszony perspektywą dalszego ułatwienia sobie życia przeszedłem do bojów ze SpringIDE. Po skończonej czyności ponownie odpaliłem Eclipse. W menu kontekstowym pojawiła się nowa magiczna opcja: "Add Spring Project Nature". Zadowolony z odniesionych rezultatów postanowiłem rozpocząć testowanie pierwszego pluginu. I co się okazało? Plugin Hibernate Tools wyparował... Logi Eclipse zamilkły. Wszelkie próby wystartowania Eclipse z opcją clean nie przyniosły oczekiwanego rezultatu. Nie pomogła również ponowna instalacja owego plugina.
Pogooglam jeszcze jutro. Jeśli nie znajdę na sieci jakiegoś workaround to daję sobie spokój z Hibernate Tools. Mam na przyszłość nauczkę, żeby nie ufać pluginom w wersji beta ;)