Play Framework – Ebean jako ORM

W poprzednim wpisie pokazałem w jaki sposób zbudować w pełni funkcjonalne, proste API restowe z użyciem Frameworka Play.
W tym i kolejnych wpisach pokażę w jaki sposób połączyć się z bazą danych i jak użyć wszystkich fajnych funkcji tego nowoczesnego frameworka.

Wpisy podzielę na kilka części:

  • baza danych – to ten wpis
  • akka – opublikowane – zajrzyj tutaj
  • pule wątków – w przygotowaniu
  • obsługa błędów – w przygotowaniu
  • testy – w przygotowaniu

Po tych wpisach zobaczycie, że można dość prosto napisać dobrze skalującą się aplikację, która będzie działała szybko bez względu na to, czy będzie jeden odwiedzający, czy będzie ich wielu.

Wymagania

  • Czysty projekt z frameworkiem Play! w wersji 2.6.x
  • Podstawowa znajomość JPA
  • Podstawowa znajomość programowania funkcyjnego w Java 8
  • 15 minut wolnego czasu

Konfiguracja

Aby używać bazy danych, musimy jakąś mieć 🙂

Użyjemy bazy H2 
Jest ona bardzo wygodna dla prostych potrzeb developerskich, a dodatkowo, potrafi działać jako embeded database, która rezyduje w pamięci, a więc nic nie trzeba instalować, a po każdym włączeniu/wyłączeniu aplikacji, mamy nową bazę danych.

Użyjemy też Ebean’a jako ORM’a. Nie będę tutaj udowadniał, czy jest on lepszy czy gorszy od Hibernate’a. Jest trochę inny, ma kilka fajnych funkcji, a wydajnościowo nie jest ani lepszy, ani gorszy od innych ORMów.

Najpierw dodajmy Ebeana:

Do pliku project/plugins.sbt dodajemy linijkę:

Mamy już Ebean’a na pokładzie. Trzeba go jeszcze włączyć:

W pliku build.sbt mamy linijkę:

Zamieniamy ją na:

Dodatkowo musimy dodać kilka zależności do pliku build.sbt:

Co do tej pory wykonaliśmy:

  • Dodaliśmy plugin ebean
  • Włączyliśmy obsługę ebean w projekcie
  • Dodaliśmy biblioteki odpowiedzialne za obsługę JDBC oraz H2

Model

Czas zdefiniować jakąś tabelkę, coś co będzie w bazie danych.

Utworzymy pakiet models, a w nim dodamy klasę Person:

 

Standardowe adnotacje JPA nie powinny być zagadką, więc ich nie opisuję.
W oczy rzuca się to, że klasa extenduje Model.

Model to klasa Ebean’a, która dodaje do tej klasy całą magię związaną z obsługą bazy danych.

Finder

Ebean udostępnia Finder. Jest to obiekt, dzięki któremu odpytujemy naszą bazę danych.
Definiujemy go dla każdej klasy osobno. W przypadku Person, będzie to:

Pierwszy parametr to typ klucza głównego. W naszym przypadku jest to Long.
Drugi parametr to klasa, którą opisujemy.

Za pomocą Finder’a możemy odpytywać bazę danych. Opis wszystkich metod znacznie wykracza poza ramy tego wpisu, więc opiszę tylko podstawowe metody, jakie są używane w większości przypadków 😉

  • Wyszukanie identyfikatora
  • Wyszukanie po nazwie pola:
  • Wyszukanie wszystkiego:

Oczywiście ebean potrafi dużo więcej, ale jak widać, zasada jest taka: FINDER.query().where()…….findList()

To teraz po wszystkich dodatkowych metodach, nasza klasa Person wygląda tak:

 

Json

Nie będziemy przyjmowali bezpośredniego modelu jako Json’a. Potrzebujemy do tego osobnej klasy.
Są oczywiście przykłady, które operują bezpośrednio na modelach, ale ja wolę starą szkołę operowania na DTO.

Utworzymy pakiet json i dodamy do niego klasę PersonJson:

 

Nic strasznego 🙂

I jeszcze konwerter, który dokona konwersji PersonPersonJson:

Proste 🙂

Kontroler

Tutaj zepniemy to wszystko w całość. Już prawie koniec.

Chcemy poprzez api wykonać operacje:

  • dodania osoby
  • pobrania osób
  • pobrania osoby po id

Nic prostszego. Mamy wszystko co potrzebujemy, aby to zrobić, a z poprzedniego wpisu, wiemy jak, pozostaje nudna implementacja:

Zdefiniowaliśmy kontroler, wstrzyknęliśmy konwerter, i utworzyliśmy kilka metod.
Jedyna uwaga co do zapisu.
W momencie jak rozszerzyliśmy klasę Person o Model, dostaliśmy od Ebean’a metody save(), update(), delete(). Chyba nie muszę opisywać, co one robią 🙂

routes

Jeszcze ustalmy ścieżki:

plik routes:

 

Konfiguracja bazy danych

Na sam koniec – musimy jeszcze skonfigurować samo połączenie do bazy danych i powiedzieć gdzie trzymamy klasy modelowe.

Otwieramy application.conf i wpisujemy tam:

 

To wszystko.

Uruchamiamy aplikację, po pierwszym wprowadzeniu dowolnego adresu w przeglądarce, dostaniemy komunikat, że baza danych nie jest zainicjowana. Play sam się zajmuje ewolucjami baz danych i jeśli nie skonfigurujemy inaczej, to musimy zatwierdzić ewolucję. Potem już wszystko leci jak trzeba 🙂 Konfiguracja ewolucji jest pięknie opisana tutaj

W kolejnym wpisie zajmę się przerobieniem naszej aplikacji na bardziej reactive, rozdzielimy trochę logikę i uporządkujemy kod.