Monthly Archives: February 2013

Prosty projekt dla Hibernate jako JPA2

W poprzednim wpisie poświęconym certyfikacji JPA wspominałem o tym, że dla nauki najbardziej wygodnym podejściem jest korzystanie z Hibernate w aplikacji konsolowej. Postanowiłem dla ułatwienia zamieścić bardzo prosty projekt (w oparciu o Mavena), aby pomóc w rozpoczęciu pracy.

Tworzymy w naszym IDE projekt Mavenowy. Grupy, artefakty i wersje pozostawiam już do swobodnej interpretacji. Najważniejsze są wszystkie zależności. Mój plik POM wygląda tak (zbudowany na podstawie jednego z przykładów dostępnych w sieci, nie pomnę juz skąd dokładnie):

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
 http://maven.apache.org/maven-v4_0_0.xsd">
 <modelVersion>4.0.0</modelVersion>
 <groupId>com.wordpress.chlebik</groupId>
 <artifactId>jpa</artifactId>
 <version>1.0.0</version>
 <packaging>jar</packaging>

 <properties>
 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
 <maven.compiler.source>1.7</maven.compiler.source>
 <maven.compiler.target>1.7</maven.compiler.target>

 <hibernate.version>4.1.2.Final</hibernate.version>
 <org.apache.derby.version>10.8.1.2</org.apache.derby.version>

 <log4j.version>1.2.16</log4j.version>
 <slf4j.version>1.6.4</slf4j.version>

 </properties>

 <repositories>
 <!-- Hibernate Repository -->
 <repository>
 <id>jboss</id>
 <name>JBoss Release Maven Repository</name>
 <url>https://repository.jboss.org/nexus/content/repositories/releases/</url>
 </repository>
 </repositories>

 <pluginRepositories>
 <pluginRepository>
 <id>jboss-public-repository-group</id>
 <name>JBoss Public Maven Repository</name>
 <url>https://repository.jboss.org/nexus/content/groups/public-jboss/</url>
 <snapshots>
 <enabled>true</enabled>
 </snapshots>
 <releases>
 <enabled>false</enabled>
 </releases>
 </pluginRepository>
 </pluginRepositories>

 <dependencies>

 <dependency>
 <groupId>com.h2database</groupId>
 <artifactId>h2</artifactId>
 <version>1.2.145</version>
 </dependency>

 <dependency>
 <groupId>org.hibernate</groupId>
 <artifactId>hibernate-core</artifactId>
 <version>${hibernate.version}</version>
 </dependency>
 <dependency>
 <groupId>org.hibernate</groupId>
 <artifactId>hibernate-entitymanager</artifactId>
 <version>${hibernate.version}</version>
 </dependency>
 <dependency>
 <groupId>org.hibernate</groupId>
 <artifactId>hibernate-c3p0</artifactId>
 <version>${hibernate.version}</version>
 </dependency>
 <dependency>
 <groupId>org.hibernate</groupId>
 <artifactId>hibernate-ehcache</artifactId>
 <version>${hibernate.version}</version>
 </dependency>
 <dependency>
 <groupId>org.hibernate</groupId>
 <artifactId>hibernate-annotations</artifactId>
 <version>3.5.6-Final</version>
 </dependency>
 <dependency>
 <groupId>org.hibernate</groupId>
 <artifactId>hibernate-validator</artifactId>
 <version>4.2.0.Final</version>
 </dependency>

 <dependency>
 <groupId>log4j</groupId>
 <artifactId>log4j</artifactId>
 <version>${log4j.version}</version>
 </dependency>
 <dependency>
 <groupId>org.slf4j</groupId>
 <artifactId>slf4j-api</artifactId>
 <version>${slf4j.version}</version>
 </dependency>
 <dependency>
 <groupId>org.slf4j</groupId>
 <artifactId>jcl-over-slf4j</artifactId>
 <version>${slf4j.version}</version>
 </dependency>
 <dependency>
 <groupId>org.slf4j</groupId>
 <artifactId>slf4j-log4j12</artifactId>
 <version>${slf4j.version}</version>
 </dependency>

 <dependency>
 <groupId>commons-lang</groupId>
 <artifactId>commons-lang</artifactId>
 <version>2.6</version>
 </dependency>
 </dependencies>

</project>

Do poprawnego działania potrzebujemy jeszcze dwóch rzeczy – persistence.xml oraz kodu (głównej klasy uruchamiającej oraz klasy domenowej). Zaczniemy od persistence.xml (w folderze /main/src/resources/META-INF).


<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence                                   http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
  <persistence-unit name="persistenceUnit" transaction-type="RESOURCE_LOCAL">
    
   <class>com.wordpress.chlebik.jpa.domain.Hero</class>
     
   <properties>
         <property name="javax.persistence.jdbc.driver" value="org.h2.Driver" />
         <property name="javax.persistence.jdbc.url" value="jdbc:h2:mem:db1;DB_CLOSE_DELAY=-1;MVCC=TRUE" />          
         <property name="javax.persistence.jdbc.user" value="sa" />
         <property name="javax.persistence.jdbc.password" value="" />

         <property name="hibernate.show_sql" value="true" />
         <property name="hibernate.hbm2ddl.auto" value="create" />
     </properties>
   
  </persistence-unit>
</persistence>


No i potem mamy klasę uruchomieniową:

package com.wordpress.chlebik.jpa;

import java.util.Date;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.wordpress.chlebik.jpa.domain.Hero;

public class App {
    
    public static void main(String... args) {

   EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory( "persistenceUnit" );
   EntityManager entityManager = entityManagerFactory.createEntityManager();

		entityManager.getTransaction().begin();
		Hero h = new Hero();
		h.setCreationDate(new Date());
		h.setLevel(1);
		h.setName("Chlebikowy Mag");
		entityManager.persist( h );

		entityManager.getTransaction().commit();
		entityManager.close();

    }
}

No i na koniec wspomniana klasa encji:

package com.wordpress.chlebik.jpa.domain;

import java.util.Date;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;

import org.hibernate.annotations.GenericGenerator;

@Entity
@Table( name = "HEROES" )
public class Hero {

    @Id
    @GeneratedValue(generator="increment")
    @GenericGenerator(name="increment", strategy = "increment")
    private Long id;

    @Temporal(TemporalType.TIMESTAMP)
    private Date creationDate;

    private String name;
    private Integer level;

    public Hero() { }

    // Gettery i settery ucięte

}

Taki prosty szkielet programu umożliwi nam pracę z JPA opierając się na bazie danych H2 uruchamianej w pamięci za każdym startem naszej aplikacji. Kompilacja i uruchomienie aplikacji trwa mgnienie oka, zaś dzięki Mavenowi bardzo łatwo jest ew. podmienić dostawcę JPA czy szybko przerobić projekt na appkę webową uruchamianą w kontenerze JEE.

Dla ułatwienia sobie prac i nauki można dorzucić jeszcze dwie rzeczy – logowanie oraz podgląd bazy danych. Logowanie dodać można bardzo prosto – do folderu /src/main/resources należy dodać plik log4j.properties, u mnie wygląda on tak:

log4j.rootLogger=WARN, stdout

log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%n%m%n%n

I dzięki temu w naszej głównej klasie możemy sobie utworzyć obiekt loggera:

private static final Log log = LogFactory.getLog(App.class);

Dzięki czemu można obyć się bez System.out.println. Drugą sprawą jest baza danych i ew. podgląd jej zawartości. Zasadniczo przy używaniu JPA nie powinniśmy w ogóle dotykać bazy danych jako takiej. Jednakże jest to raczej pobożne życzenie – bardzo często JPA jest wprowadzane do istniejącego już schematu bazy. Do tego dobrze jest czasem popatrzeć czy aspekty wydajnościowe (klucze przede wszystkim) zostały poprawnie przez JPA rozpoznane. Tak jak pisałem w przypadku powyższej aplikacji baza danych jest przechowywana w pamięci i jako taka jest usuwana po zakończeniu działania programu. Czasem jednakoż dobrze byłoby przyjrzeć się wygenerowanym tabelom, relacjom czy zapisanym danym. Możemy to osiągnąć uruchamiając bazę H2 jako oddzieny proces w trybie serwerowym. By to osiągnąć trzeba oczywiście zaciągnąć plik JAR z bazą H2. Myślę, że strona domowa bazy jest świetnym miejscem by ten plik uzyskać. Po jego ściągnięciu na dysk trzeba plik JAR uruchomić (w Windowsie wystarczy na niego kliknąć). Pojawi się mniej więcej takie okienko.

H2Console

Odpowiednie pola trzeba wypełnić dokładnie takimi samymi wartościami jak powyżej. Po zrobieniu tego dajemy ‘Połącz’ i w przeglądarce mamy już dostęp do naszej bazy. Teraz wystarczy zmienić plik persistence.xml w miejscu dotyczącym połączenia.

<property name="javax.persistence.jdbc.url" value="jdbc:h2:tcp://localhost/~/test;AUTO_SERVER=TRUE;DB_CLOSE_DELAY=-1" />

I każdorazowe uruchomienie naszej aplikacji będzie łączyć się do bazy danych, ale stworzone tabele/relacje/dane zostaną zapisane i będą dostępne do przeglądania dopóki nie wyłączymy procesu H2. Oczywiście baza danych musi być odpalona 😉

Advertisements

Encje i cały ten bałagan

Przyszedł czas by rozpocząć zabawę w certyfikację JPA. W dzisiejszym wpisie zamierzam przedstawić pokrótce podstawowe pojęcia i zagadnienia dotyczące mapowania ORM, encji i o co w ogóle chodzi z tymi pojęciami.

Encje

Podstawowym pojęciem w przypadku mapowania relacyjno-obiektowego oraz persystencji jest encja. Z pewnością spotkaliście się z tym pojęciem w wielu różnych znaczeniach. Nasza książeczka definicuje ją krótko i treściwie:

An entity is essentially a noun, or a grouping of state associated together as a single unit. It may participate in relationships to any number of other entities in a number of standard ways. In the object-oriented paradigm, we would add behavior to it and call it an object.

Jest to bardzo krótka i treściwa charakterystyka. Nasuwającym się pytaniem jest – jakie to cechy musi posiadać obiekt, aby uznać go za encję? Jest ich kilka:

  • Persistability – encje jako takie muszą mieć możliwość być zapisanymi w bazie danych.
  • Identity – obiekt, który chcemy uznać za encję musi być jednoznacznie identyfikowalny pomiędzy innymi podobnymi sobie obiektami. Jeśli bowiem mamy dokonywać operacji na obiekcie musimy mieć pewność, że dokonujemy ich na wybranym przez nas obiekcie, a nie pierwszym lepszym, który się nawinął. Dla nas oznacza to, że obiekt posiada unikalny klucz.
  • Transactionality – encje muszą być ‘transakcyjne’ (mam nadzieję, że to prawidłowe tłumaczenie) – móc istnieć w kontekście transakcji. Do transakcji wrócę później.
  • Granularity – słowo to można przetłumaczyć jako ‘ziarnistość’. Chodzi o to, aby encja była pełnoprawnym obiektem, który trzyma w sobie nie pojedynczą wartośc (o prymitywie nie wspomnę), ale kilkanaście cech/obiektów, które tworzą logiczną całość. Tworzenie encji do trzymania ID i jednego łańcucha tekstowego jest możliwe, ale raczej mało (najczęściej) sensowne.

Encja jako taka poza informacjami, które przechowuje ‘sama w sobie’ (czyli po prostu swoimi własnościami) może posiadać tzw. metadane. Opisują one w jaki sposób encja ma się zachować w środowisku JPA. Zasadniczo jak większość tego typu danych w Javie możemy zapisać je na dwa sposoby – adnotacjami bądź też za pomocą XMLa. Wszystkie adnotacje, o których tutaj mowa znajdują się w pakiecie javax.persistence.*. Plików XML obecnie głównie używa się do stworzenia pliku konfiguracyjnego dla JPApersistence.xml, który opisuje w jaki sposób będą zachowywały się nasze encje oraz dokładniejsze dane konfiguracyjne (najczęściej specyficzne dla dostawcy JPA). Oczywiście nic nie stoi na przeszkodzie, aby za ich pomocą również mapować encje. Jednakże od takiego podejścia się odchodzi (generuje duże ilości XMLa i rozbija informacje będące dla encji istotne na 2 pliki). W tutorialach oczywiście będę posługiwał się tylko adnotacjami (dla czystości kodu przede wszystkim).

Ok. Wiemy jakie cechy powinna mieć encja. Nie zbliżyliśmy się jednakże choćby odrobinę do stworzenia takowej z obiektu. Do tego zasadniczo potrzeba dwóch rzeczy:

  • adnotacji @Entity – adnotacja markerowa używana na poziomie klasy
  • adnotacji @Id – adnotacja markerowa używana na poziomie własności obiektu (lub metody dostępowej – o tym później).

Trochę wyprzedzając temat – brak adnotacji @Entity przy wpisaniu klasy jako potencjalnej encji w pliku konfiguracyjnym skutkuje błędem czasu wykonania (np. przy próbie zapisu encji). Brak adnotacji @Id z kolei zaowocuje wyjątkiem podczas wykonania (u mnie wyleciał org.hibernate.AnnotationException docelowo opakowanym w javax.persistence.PersistenceException). Zasadniczo wszystkie błędy niższego poziomu docelowo są wrapowane w PersistenceException.

Spójrzmy zatem na przykładową encję. Dodam znów na marginesie – modelem, którego będziemy używać jest gra RPG – będziemy zatem mieli encję reprezentującą gracza, jego cechy, posiadane przedmioty i co tam mi jeszcze do głowy przyjdzie. Zakładam, że będzie to troszkę bardziej przemawiające niż po raz milionowy przykłady typu User, Phone czy Address.

package com.wordpress.chlebik.jpa.domain;

import java.util.Date;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;

import org.hibernate.annotations.GenericGenerator;

@Entity
@Table( name = "HEROES" )
public class Hero {

    @Id
    @GeneratedValue(generator="increment")
    @GenericGenerator(name="increment", strategy = "increment")
    private Long id;

    @Temporal(TemporalType.TIMESTAMP)
    private Date creationDate;

    private String name;
    private Integer level;

    public Hero() { }

    public Long getId() {
		return id;
    }

    private void setId(Long id) {
		this.id = id;
    }

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Integer getLevel() {
		return level;
	}

	public void setLevel(Integer level) {
		this.level = level;
	}

	public Date getCreationDate() {
		return creationDate;
	}

	public void setCreationDate(Date creationDate) {
		this.creationDate = creationDate;
	}
}

Konkretnymi adnotacjami sugeruję na razie się nie przejmować (wrócę do tego). Jak widać nasza encja jest prostym POJOsem z dodatkami. Pytanie powinno brzmieć – gdzie i w jaki sposób taki obiekt zostanie zapisany w bazie danych? Zasada jest prosta – o ile nie jest ustawione inaczej wszystkie własności obiektu zostaną zapisane do bazy danych. Niezależnie od tego czy istnieją akcesory! Gdzie zapisane? Ano tutaj warto przyjrzeć się dokładniej adnotacji @Table – posiada ona atrybut o nazwie (jakże inaczej) – name. Wskazuje on na nazwę tabeli w bazie danych. Jeżeli atrybutu tego brak – wówczas w charakterze nazwy tabeli zostanie użyta nazwa encji.

EntityManager

Sama encja jest bardzo fajnym wynalazkiem. Zgódźmy się jednak – sama to ze sobą nic nie zrobi. Tutaj na scenę wkracza kolejne pojęcie-klucz – EntityManager. Jest to interfejs, który dostarcza funkcjonalności, dzięki którym w ogóle możemy mówić o operacjach bazodanowych (wyszukiwanie, zapisywanie i wszystko inne). Konkretne implementacje EntityManagera pobieramy korzystając z innego interfejsu o nazwie EntityManagerFactory. Zaś konkretne EntityManagerFactory są jednoznacznie powiązane z pojęciem PersistenceUnit. Jest to zdefiniowana w pliku persistence.xml ‘jednostka’, w której określamy klasy, które będą encjami w ramach PersistenceContext dostarczanego przez EntityManagera, a także właściwości połączenia do bazy danych. Rozumiecie? Pewnie że nie, ja też bym w tym momencie nie zrozumiał 😉

Poniżej mały rysunek.

Persistence UML

Zaś dalej sensownym do przeczytania wydaje się być materiał, do którego linkowałem już w pierwszym wpisie o JPA. EntityManagerFactory – obiekt bez którego ani rusz – w Javie SE otrzymujemy po prostu korzystając ze statycznej metody klasy Persistence. Kiedy mamy fabrykę wyciągnięcie EntityManagera jest trywialne:

EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory( "persistenceUnit" );
EntityManager entityManager = entityManagerFactory.createEntityManager();

Tadam! Mamy EntityManagera i możemy ruszać na podbój świata 😉 Poza podbojem możemy też zająć się bardziej przyziemnymi rzeczami:

  • zapisywaniem encji w bazie (INSERT) – w taki oto choćby sposób:
    Hero h = new Hero();
    h.setCreationDate(new Date());
    h.setLevel(1);
    h.setName("Chlebikowy Mag");
    entityManager.persist( h );
    
  • wyszukaniem encji w bazie (SELECT) – posiłkując się kluczem głównym oraz typem encji:
    Hero h = entityManager.find(Hero.class, 1L);
    
  • usuwaniem encji (DELETE) – z małą pomocą wyszukiwania:
    Hero h = entityManager.find(Hero.class, 1L);
    entityManager.remove(h);
    
  • zmianą encji (UPDATE) – o dziwo bez konieczności używania EntityManagera do przeprowadzenia aktualizacji:
    Hero h = entityManager.find(Hero.class, 1L);
    h.setName("Chlebikowy wojownik");
    

Proste prawda? Aż miło popatrzeć jak odwieczne ‘SELECT * FROM’ i insze klony odchodzą powoli do lamusa.

Transakcje i SQL

By zakończyć temat ciekawych zastępników odniosę się jeszcze do transakcji i zapytań. Zasadniczo omawiany przeze mnie przykład dotyczy JPA uruchamianego poza środowiskiem EE (np. z aplikacji ‘konsolowej’ czy w Tomcacie). Używanie JPA w ramach serwera aplikacyjnego będzie poruszane w odpowiednich momentach (w aplikacjach JEE EntityManagera po prostu wstrzykujemy używając adnotacji), jednakże dla nauki łatwiej jest posiłkować się najprostszą możliwą aplikacją (głównie chodzi o szybkość uruchamiania). Wspominam o tym dlatego, iż w przypadku takich aplikacji wszystkie operacje zmieniające dane w bazie wymagają ‘wrapowania’ w transakcję. By nie zaciemniać zagadnienia (do transakcji powrócę w następnych wpisach) kawałeczek kodu jak powinny wyglądać przedstawione powyżej operacje (CUD).

entityManager.getTransaction().begin();

Hero h = new Hero();
h.setCreationDate(new Date());
h.setLevel(1);
h.setName("Chlebikowy Mag");
entityManager.persist( h );

entityManager.getTransaction().commit();

Do tej pory używaliśmy metod EntityManagera by osiągnąć zamierzony cel. W codziennej praktyce programistycznej pojawiają się często sytuacje, w których samo find nie wystarczy. Co zrobić kiedy potrzebujemy wykonać troszeczkę bardziej skomplikowane zapytanie? Z pomocą przychodzą nam wówczas również metody EntityManagera, które pozwalają na tworzenie obiektów zapytań. Reprezentowane są one przez dwa podstawowe interfejsy – TypedQuery oraz Query. Przykład tego pierwszego poniżej:

TypedQuery query = entityManager.createQuery("SELECT h FROM Hero h", Hero.class);
List heroes = query.getResultList();

Plik konfiguracyjny persistence.xml

Do tej pory głównie skupiałem się na encjach oraz pobocznym kodzie. O konfiguracji samego JPA wspomniałem niejako mimochodem. Prawda jednak jest taka, iż istnienie pliku persistence.xml jest warunkiem koniecznym dla poprawnego działania całej powyższej magii. Plik ten znajduje się w folderze META-INF (w projektach Mavena folder ten powinien leżeć w /src/main/resources). Mój dość podstawowy plik (z konfiguracją bazy danych H2 dla prostoty uruchamiania i działania) wygląda następująco:

<!--?xml version="1.0" encoding="UTF-8"?-->


 com.wordpress.chlebik.jpa.domain.Hero





 

Najistotniejszymi elementami jest nazwa naszego persistence-unit (używa się jej do stworzenia instancji EntityManagerFactory), lista klas encyjnych oraz podstawowe własności dla połączenia. Przed specyfikacją JPA w wersji 2 nazwy własności bywały różne (w zależności od bazy danych), co powodowało zrozumiałe problemy. Obecnie gdzie tylko to możliwe nazwy te są zestandaryzowane jak tylko się da.

Oracle Certified Expert, Java EE 6 Java Persistence API Developer – Here I come!

Jak wspomniałem w niedawnym wpisie zabrałem się do kolejnej certyfikacji. Trochę się zmieniło od czasów kiedy zdawałem SCJP, ba, Sun zniknął wykupiony przez Oracle. W sumie wyszło mi to na dobre – interesujący mnie egzamin to wprowadzony nie aż tak dawno temu Oracle Certified Expert, Java EE 6 Java Persistence API Developer.

Dlaczego ten certyfikat? Kontynuowanie dalszego zgłębiania się w meandry samej Javy na poziomie certyfikacyjnym niespecjalnie jest dla mnie korzystne. Oczywiście zawsze lepiej jest wiedzieć więcej niż mniej, jednakże w sytuacji ograniczonego czasu lepiej skupić się na czymś, co może pomóc na co dzień w pracy zawodowej. Swego czasu myślałem o certyfikacji z webserwisów. Po przejrzeniu materiałów dostępnych w sieci pomysły certyfikacji w webserwisach odłożyłem na półkę 😉 . Certyfikat webdevelopmentu uważam za zasadniczo niepotrzebny – samą książkę przygotowującą do niego (z serii Head First) czytałem dawno temu kiedy w ogóle poznawałem Javę. Dzisiaj w dobie używania frameworków webowych podstawowa znajomość servletów i JSP absolutnie wystarcza by wiedzieć co z czym – w razie potrzeby można zajrzeć do książki (uuups, okazało się, że podpiera ona mój monitor 😉 . Z certyfikatem dotyczącym całego JEE sprawa jest jeszcze bardziej skomplikowana – obejmuje bardzo duży zakres wiedzy, niespecjalnie póki co przydatnej dla mnie w codziennej pracy.

Inne certyfikaty najczęściej wymagają zrealizowania kursów Oracle, ergo, wydania dużych pieniędzy. Na placu boju pozostał zatem wykrojony z certyfikacji biznesowej egzamin poświęcony JPA. Kilka miesięcy temu miałem okazję ostro przysiąść z tą technologią. Czasem braki w teoretycznej wiedzy (specyfikacja you fool!) doprowadzały mnie wtedy do szału. W sumie przyszedł też czas na ponowne rozruszanie bloga – wipsy dotyczące SCJP póki co cieszą się wciąż bardzo wysoką oglądalnością.

Od czego zacząć? Myślę, że od wymagań. Znaleźć je można na stronie Oracle (miejmy nadzieję, że nie zmienią tego adresu, strony Oracla to największe badziewie jakie widziałem). Na pewno przyda się również podstawowa broń każdego podchodzącego do certyfikacji – specyfikacja JPA. Z całą pewnością wypada odwiedzić na początek stronę JavaRanch poświęconą właśnie temu egzaminowi. Znaleźć tam można całą masę ciekawych wątków, między innymi z czego się uczyć (podstawą jest książką Pro JPA 2 i specyfikacja), jak poszło innym zdającym, ciekawe są również wątki o symulatorach egzaminów. Na sam koniec zostawiłem kilka ciekawych źródeł w internecie (listę będę uzupełniał jak tylko znajdę coś ciekawego):

  • JPA Concepts – cholernie czytelne wprowadzenie do słownictwa JPA. Jeśli do tej pory nie do końca rozumiesz różnicę między PersistenceContext, a EntityManagerem to jest to świetne miejsce by zacząć.
  • JPA Quiz – zebrane w jednym miejscu kilkaset krótkich pytań i odpowiedzi dotyczących JPA.
  • JPA Mappings – ciekawa ni to appka, ni to wiki poświęcona mapowaniu relacji.
  • JPA Tutorial – skrócona wersja tego, co ja zamierzam zaprezentować w formie całego cyklu
  • Oracle Docs – strona dokumentacji Oracle poświęcona persystencji

Myślę, że formuła wpisów będzie troszeczkę inna niż w przypadku SCJP – książka Pro JPA2 nie jest oficjalnym podręcznikiem egzaminacyjnym zatem nie zawiera pytań na końcach rozdziałów. Postaram się zatem tworzyć streszczenia rozdziałów wraz z przykładami kodu (gdzie ma to sens), a także dorzucać jakieś ciekawe pytania i problemy przedstawiane we wpisach. Jednakże to się jeszcze okaże. Mój plan jest taki, aby w przykładach i efektywnym kodowaniu używać Hibernate – z moich dotychczasowych doświadczeń z dostawcami JPA ten jako jedyny nie pozostawił wielkiego WTF 😉 That’s all folks.

Powiew książkowej świeżości

W ostatnim czasie po raz kolejny coś się ruszyło w kwestii wydawniczej w Polsce. Rodzimy Helion w końcu poszedł po rozum do głowy i zabrali się za wydawanie troszeczkę bardziej sensownych pozycji dotyczących interesującego nas poletka. Mieli już przebłyski wcześniej, ale tym razem wygląda to jak stały trend. Obecnie wydali (bądź też planują wydać) kilka ciekawych pozycji.

Mogą pojawić się głosy, że przecież:

  • głupotą jest czytać książki papierowe – jak kto woli, ja jestem fetyszystą książkowym i do przesiadki na ebooki jakoś się nie palę
  • czekanie na polskie wydania jest śmieszne, technologia staje się stara zanim przetłumaczą – może tak, może i nie. Zasadniczo oczywistym jest, że kiedy potrzebujemy wyuczyć się na szybko nowej technologii to sięgamy po oficjalną dokumentację na sieci. Jednakże stoję na stanowisku, że czym innym są tutoriale i dokumentacja, a czym innym książka. To moje zdanie i będę się go trzymał.
  • po polsku? Angielskiego nie znasz? – zasadniczo to znam, całkiem nawet znośnie. Jednakże o ile na co dzień spędzam sporo czasu wertując źródła angielskojęzyczne, chciałbym móc dla luzu (np. w pociągu) przeczytać coś w rodzimym języku. Ot tak tylko dla odmiany i rozluźnienia.

Co tam zatem Helion nam gotuje?

  • Clojure – daleko mi wciąż do programowania funkcyjnego, ale Jacek Laskowski jak zawsze robi ciekawy hype wokół zagadnienia zatem jest to rzecz warta uwagi. Dla tych, co nie chcą czekać mam inną pozycję – Język programowania Scala
  • Spring in Action – moim zdaniem najfajniejsza książka o Springu wreszcie doczekała się polskiego wydania. Prawdą jest, że dotyczy wersji 3.0, ale wciąż pozostaje świetnym wprowadzeniem do Springa jako takiego. Dla początkujących – bezcenna pozycja.
  • Wydajność Javy – tej książki nie miałem w rękach w wersji oryginalnej, zaskoczyła mnie zaś poruszana tematyka. Bardzo (moim zdaniem) ciekawe aspekty programowania, na które my – programiści – może nie do końca zwracamy uwagę. Z całą pewnością zapoznam się z nią bliżej zaś wrażeniami podzielę się na blogu.

Działający przykład JEE w akcji

Jakoś tak się złożyło, że poza servletami i JPA niespecjalnie miałem w życiu pobawić się w EJB i insze wynalazki. Fakt, że pojawił się kiedyś dawno Spring skutecznie zniechęcał do posiłkowania się JEE w codziennym developmencie. Jednakże sytuacja zmieniła się wraz z wydaniem wersji 6 Javy EE.

Szukając w sieci materiałów dla przygotowań do certyfikatu Java Persistence API Developer Certified Expert (tak tak, pierwsze wpisy z przygotowań już niedługo) znalazłem dość ciekawy tutorial, który umożliwia postawienie w pełni funkcjonalnej aplikacji, na której możnaby przećwiczyć mniej i bardziej zaawansowane tematy związane z tą certyfikacją.

JBoss to nazwa budząca respekt. Jako firma oferuje szeroki wachlarz produktów – począwszy od serwera aplikacyjnego skończywszy na IDE. Oferuje również strasznie fajny tutorial znajdujący się  dokładnie pod tym adresem. Obejmuje on instalację dedykowanego IDE oraz przedstawia JEE w akcji – mamy i usługi sieciowe, mamy JSF, mamy też podpięte Hibernate jako ORM. Nic tylko brać i działać. Jeśli ktoś potrzebuje zobaczyć jak może wyglądać sensowna appka bez miliona zależności w POMie to powyższy adres jest świetnym punktem wyjścia.