Monthly Archives: September 2008

Ano i co tam słychować?

Słychować tyle, że chwilowo brak czasu na bloga. Jednakże dla urozmaicenia zmieniłem skórkę, gdyż stara nie za bardzo ładnie dawała sobie radę z zaznaczaniem kodu. Nowa pod tym względem prezentuje się choć trochę lepiej. Zaś poza zabawą w graficzkę z tyłu powoli nadrabiam zaległości w nauce, ale jakoś to powoli idzie. Mam nadzieję, że za dni kilka pojawi się konkretny merytoryczny wpis.

Advertisements

JDBC i MySql, trzy godziny później

W ramach nauki oczywiście przyszedł czas na bazę danych. Oczywiście na razie nie porywam się na poznawanie Hibernate, skoro często do końca jeszcze nie pamiętam samej składni języka. Jednakże w Javie zrobiono coś tak fajnego jak JDBC, a krótko mówiąc interfejs do łączenia się z bazą danych. W sieciowych tutorialach rzecz wyglądała pięknie, właśnie, wyglądała…

Po raz kolejny zostałem pokarany za podejście typowe dla programisty PHP – sklepiem kod i zacznie działać, a potem się rozszerzy i będzie dobrze. Niestety w przypadku Javy po raz kolejny okazało się, że jest to podejście zgubne i należałoby go zaniechać. Albowiem cóż można wyczytać w sieciowych tutorialach? Ano tyle, że operacje na bazie generalnie ogarniają klasy ze standardowej biblioteki z pakietu java.sql.*; lub javax.sql.*. Oczywiście zaimportowałem stosowne klasy, teraz trzeba dorzucić connector do MySQLa. Prawy klik na katalogu z bibliotekami w projekcie/add JAR/wskazanie ścieżki i już mamy śmigający connector. Można też zaimportować taki connector z pakietów, które dostarczane są razem z NetBeans, ale w sieci już jest nowsza wersja, której moje IDE jeszcze nie miało. Odpaliłem MySQLa jako proces, przezornie zalogowałem się na konsolę, no cóż, śmiga. No to teraz próbujmy połączyć się z bazą z poziomu kodu. ZONK!

W sieci znalazłem taki kod – była to część większego programiku zatem skopiowałem to, co w moim naiwnym mniemaniu powinno wystarczyć.


String driver = "com.mysql.jdbc.Driver";
Class.forName( driver );
String url = "jdbc:mysql://localhost/chlebik";
java.sql.DriverManager.getConnection( url, "root", "" );

Normalnie po kompilacji i uruchomieniu gdyby nie wywaliło błędu to znaczyłoby, że OK. No a tutaj problem, bo wciąż i wciąż kompilator mi mówi, że mam problem z wyjątkiem i by wyrzucić trzeba go wpierw przechwycić i takie tam. Myślę sobie, że jak sypie wyjątkami to znaczy, że pewnie nie ma klas do ich obsługi czyli coś nie bardzo mi łączy bibliotekę. I zaczęło się – grzebanie w CLASSPATH, grzebanie w NetBeans, rycie w Googlu. Rozwiązanie okazało się do bólu wręcz prozaiczne. Zgodnie ze swoją filozofią – koduj najszybciej jak możesz, nauczysz się lepiej po drodze – póki co nie dotarłem do zagadnienia wyjątków w Javie. I okazało się, że te w PHP to i owszem wyjątki, ale na tym podobieństwa się kończą. Zaawansowani w temacie pewnie właśnie leżą na podłodze ze śmiechu i kwiczą ze śmiechu (pozdrawiam), a tym mniej, dla których ten blog jest to wyjaśnię.

W Javie przy deklaracji klasy można wskazać, że dana klasa wyrzuca konkretny typ wyjątku(ów). Istnieje również możliwość wpisania takiej informacji w deklaracji metody. I jeśli jest to zadeklarowane w klasie/metodzie, wówczas jej wywołania muszą być wrzucone do bloku try…catch. Jeśli tego nie ma wywala błąd. Połączenie z serwerem baz danych przez JDBC również zadeklarowano jako wyrzucające odpowiedni wyjątek. Dlatego też kod musi wyglądać tak:


try {
String driver = "com.mysql.jdbc.Driver";
Class.forName( driver );
String url = "jdbc:mysql://localhost/chlebik";
java.sql.DriverManager.getConnection( url, "LOGIN", "HASLO" );
}
catch( Exception x ) {
x.printStackTrace();
}

No i z czymś takim wszystko pięknie działa. Jak widać zatem jeszcze trzeba się trochę douczyć zanim wezmę się na poważnie za pisanie pierwszej aplikacji. Jednakże z drugiej strony – mam już połączenie z bazą – pora pobawić się dalej.

Wyrażenia regularne w klasie String

Po urlopie teoretycznie powinno być lepiej niż przed nim – okazuje się, że to twierdzenie to bzdura. Wybitnie nie chce mi się nic, a tutaj blog czeka. Jednakże jak to zawsze bywa najgorzej jest zacząć, potem zaś to już z górki. Dziś na tapetę weźmiemy to, co spędza niejednemu programiście sen z powiek – oczywiście mowa o wyrażeniach regularnych.

Nie będę oczywiście dawał kursu samych wyrażeń – całkiem fajny można znaleźć u Andrzeja Gajdy – sama składnia PCRE jest zasadniczo wspólna i z jej przeniesieniem nie powinno być większych problemów. Wyrażenia regularne w Javie są obsługiwane rzecz jasna obiektowo, jednakże w inny niż w PHP sposób. Służą do tego klasy java.util.regex.*, których jednakże opisywanie mija się z celem. Zapraszam do dokumentacji, a także do tutoriala firmy Sun, gdzie można sobie o nich konkretnie poczytać. Ja natomiast dziś pragnę zwrócić uwagę na kilka metod, które do obsługi wyrażeń regularnych oferuje nam stara dobra klasa String

Po co zasadniczo tak rozbita obsługa wyrażeń regularnych? Wiem, wiem, że w PHP mamy kochanie preg_match i problemy się rozwiązują. Jednakże dość często zachodzi konieczność sprawdzenia za pomocą wyrażeń regularnych prostej wartości tekstowej, np. adresu email czy numeru konta. Zatem by nie uruchamiać całej maszynerii regexów w Javie (przypominam – java.util.regex.*), w klasie String zaimplementowano kilka malutkich metod, które pozwalają poradzić sobie z tym problemem. Pierwszą z nich jest String.match(“wyrazenie”). Ograniczona funkcjonalność pozwala tylko i wyłącznie na dopasowanie całego łańcucha znaków jako wyrażenia regularnego. Wystarczy spojrzeć na ten poniższy kod:


public class TestRegular {
public static void main(String[] args){
String wzorzec = "\\d";
String lancuch = "5";
System.out.print(lancuch.matches(wzorzec));
}
}

Metoda matches zwraca zawsze wartość bool – jeśli podany łancuch jest zgodny z podanym wyrażeniem (podkreślam raz jeszcze – cały łańcuch!!!), wówczas otrzymujemy TRUE, w przeciwnym wypadku oczywiście FALSE. Nazwy zmiennych chyba dość jasno obrazuja co i jak. Istotną tylko rzeczą jest fakt, że znaki specjalne (w tym przypadku określenie zbioru cyfr – “\w”, musi zostać oznaczone dodatkowym shashem by zadziałało poprawnie).

Drugą metodą jest replaceAll, która jak można się domyśleć zamienia wszystkie pasujące do wzorca elementy ciągu na inne. Oto przykład:


public class TestRegular {
public static void main(String[] args){
String mojLancuch = "Chlebi5 to programista PHP, ale Chlebik chce programować w Javie.";
System.out.print(mojLancuch.replaceAll("Chlebi\\d","Michał"));
}
}

Jak widać w wejściowym ciągu znaków specjalnie dorzuciłem cyfrę zamiast ostatniej litery mojego nicka i w ten sposób tylko pierwszy wyraz w ciągu został zamieniony (drugi nie został w ogóle przez Javę zauważony). Natomiast gdybyśmy chcieli tylkoi wyłącznie zamienić pierwsze wystąpienie kawałka ciągu, który byłby zgodny ze wzorcem należy zastosować metodę replaceFirst. Oto kod:


public class TestRegular {
public static void main(String[] args){
String mojLancuch = "Chlebik to programista PHP, ale Chlebik chce programować w Javie.";
System.out.print(mojLancuch.replaceFirst("Chlebik","Michał"));
}
}

Efektem będzie “Michał to programista PHP, ale Chlebik chce programować w Javie”. Dość to proste i logiczne. Na sam koniec zostawiłem bardziej skomplikowany przykład. Otóż pewnie niejeden raz programista PHP ma okazję skorzystać w pięknej funkcji jaką jest explode. Ano i w Javie mamy też takie explode i to do tego separatorem jest wyrażenie regularne. Rzecz nieraz przydatna, ale przedstawiona metoda (o nazwie split), ma jeden haczyk. Otóż jeśli separator znajduje się na końcu lub początku dzielonego łańcucha, w zwracanej przez metodę tablicy znajdzie się jeszcze jeden element (tablica to oczywiście tablica obiektów String) o długości zero. Przedstawia to poniższy kod:


public class TestRegular {
public static void main(String[] args){
String mojLancuch = "Chlebi5 to programista PHP, ale Chlebi5 chce programować w Javie.";
String[] mojaTablica;
mojaTablica = mojLancuch.split("Chlebi\\d");
for (String t : mojaTablica) {
System.out.println("Element tablicy to: " + t);
}
}
}

W wyniku działania programu na wyjściu dostaniemy taki oto efekt:

Element tablicy to:
Element tablicy to: to programista PHP, ale
Element tablicy to: chce programować w Javie.

Należy o tym pamiętać i potencjalnie przyciąć tablicę z początku lub końca. Metoda ta może również otrzymać jeszcze jeden parametr, jakim jest liczba zwracanych elementów. I tutaj kolejna uwaga – ilość zwróconych elementów nie oznacza przycięcia łańcucha? Najlepiej wyjaśnić to na przykładzie:


mojaTablica = mojLancuch.split("Chlebi\\d",2);

Otrzymamy wówczas tylko dwa elementy w tablicy, z czego pierwszy będzie pusty, a drugi będzie zawierał ciąg “Element tablicy to: to programista PHP, ale “. I właśnie tak nie jest! Zwracana tablica będzie miała następującą postać:

Element tablicy to:
Element tablicy to: to programista PHP, ale Chlebi5 chce programować w Javie.

Jak zatem widać zwrócona tablica zawiera w sobie cały łańcuch wejściowy, jednakże przycięty do podanej jako parametr liczby elementów.