JPA i Hibernate. Dlaczego u mnie działa tak wolno? Sławomir Sobótka



Podobne dokumenty
Java Persistence API - zagadnienia zaawansowane

JAVA PERSISTENCE API CZĘŚĆ 2 ASPEKTY ZAAWANSOWANE. Waldemar Korłub. Narzędzia i aplikacje Java EE KASK ETI Politechnika Gdańska

Podstawy frameworka Spring

Metody dostępu do danych

Wprowadzenie do Doctrine ORM

Mapowanie obiektowo-relacyjne z wykorzystaniem Hibernate

Wprowadzenie db4o - podstawy db4o - technikalia Przydatne wiadomości. Wprowadzenie. db4o. Norbert Potocki. 1 czerwca Norbert Potocki db4o

Podejście obiektowe do relacyjnych baz danych Hibernate.

Hibernate. Adrian Gawor, Adam Klekotka, Piotr Kubisz. Technologie Biznesu Elektronicznego. 12 maja 2009

JPA Java Persistance API

Java Server Faces narzędzie do implementacji w wy prezentacji

Bazy danych tworzenie aplikacji bazodanowych ORM / JPA

Programowanie komponentowe 5

Szkolenie wycofane z oferty. Program szkolenia: Enterprise Java Beans 3.0/3.1

EJB 2.x oraz zmiany w standardzie dla EJB 3.0. Michał Stanek

Wzorce dystrybucji i wspólbieżności autonomicznej

Wprowadzenie do technologii JavaServer Faces 2.1 na podstawie

Wprowadzenie do technologii JavaServer Faces 2.1 na podstawie

Java Enterprise Edition spotkanie nr 6. przygotował Jacek Sroka. Java Persistence API

Podstawowe wykorzystanie Hibernate

Zasady generowania kluczy głównych Język Java Persistence Podstawowa architektura wielowarstwowych aplikacji w oparciu o wzorce oprogramowania

EJB 3.0 (Enterprise JavaBeans 3.0)

Informacje wstępne Autor Zofia Kruczkiewicz Wzorce oprogramowania 4

Tworzenie komponentów logiki biznesowej i warstwy dostępu do danych w oparciu o EJB3.0/JPA lub EJB 3.1/JPA2

JBoss Seam: framework nowej generacji. Copyright Piotr Kochański & Erudis,

Szkolenie wycofane z oferty

Projektowanie aplikacji z bazami danych

Paweł Rajba

NHibernate Hibernate dla platformy.net. Hibernate posiada także dużą społeczność, zatem nietrudno uzyskać jakieś wsparcie w przypadku problemów.

Budowa prostej aplikacji wielowarstwowej. Laboratorium 1 Programowanie komponentowe Zofia Kruczkiewicz

ORM w Javie. Adam Michalik 2007

Instrukcja 5 Laboratorium z Podstaw Inżynierii Oprogramowania. Warstwy integracji z bazą danych: Wzorzec DAO Technologia ORM

akademia androida Składowanie danych część VI

Stanowe komponenty sesyjne

Gdzie jest moja tabela?

E:\DYDAKTYKA\ZAI\ZWWW\Laboratoria\L07\Java Persistence.doc 2011-lis-24, 17:0 Zaawansowane aplikacje internetowe Laboratorium Java Persistence.

Wzorce logiki dziedziny

Projektowanie obiektowe oprogramowania Wzorce architektury aplikacji (3) Wykład 11 Repository, Unit of Work Wiktor Zychla 2016

Projektowanie obiektowe oprogramowania Wykład 9 Wzorce architektury aplikacji (1) Wiktor Zychla 2013

Programowanie obiektowe

Kurs programowania aplikacji bazodanowych

Programowanie obiektowe

Zaawansowane aplikacje internetowe - laboratorium

Projektowanie oprogramowania. Warstwa integracji z bazą danych oparta na technologii ORM Platforma Java EE Autor: Zofia Kruczkiewicz

SPRING FRAMEWORK. dr inż. Jakub Chłapioski

1 LINQ. Zaawansowane programowanie internetowe Instrukcja nr 1

JAVA PERSISTENCE API. Wykorzystano fragmenty wykładów M. Piotrowskiego i M. Wójcika. Waldemar Korłub

Enterprise JavaBeans 3.0

Programowanie wielowarstwowe i komponentowe

Warstwa integracji. wg. D.Alur, J.Crupi, D. Malks, Core J2EE. Wzorce projektowe.

Oracle PL/SQL. Paweł Rajba.

Tomasz Dobek.

Karolina Rusin, Paweł Biczysko, Michał Olejnik. 11 maja 2009

Poznaj ASP.NET MVC. Kamil Cieślak Microsoft Student Partner

Metody dostępu do danych

Informatyka I. Standard JDBC Programowanie aplikacji bazodanowych w języku Java

Blaski i cienie wyzwalaczy w relacyjnych bazach danych. Mgr inż. Andrzej Ptasznik

Instrukcja podwaja zarobki osób, których imiona zaczynają się P i dalsze litery alfabetu zakładamy, że takich osbób jest kilkanaście.

Informatyka I. Programowanie aplikacji bazodanowych w języku Java. Standard JDBC.

Kurs programowania aplikacji bazodanowych

Contexts and Dependency Injection (CDI) Autor wykładu: Marek Wojciechowski

EJB 3.0 & JBoss Seam. 25 kwietnia 2007 Jacek Gerbszt 1

BEAN VALIDATION. Waldemar Korłub. Narzędzia i aplikacje Java EE KASK ETI Politechnika Gdańska

Programowanie w języku Java WYKŁAD

Serwery aplikacji. dr Radosław Matusik. radmat

Dostęp do baz danych w aplikacjach Java EE

Ustawienie na poziomie sesji (działa do zmiany lub zakończenia sesji zamknięcia połączenia).

1. Model ACID. 2. Deklaratywne zarządzanie transakcjami, atrybuty transakcji. 3. Propagacja transakcji. transakcje rozproszone, propagacja kontekstu

Komponenty sterowane komunikatami

Programowanie obiektowe i zdarzeniowe wykład 4 Kompozycja, kolekcje, wiązanie danych

Paweł Rajba

1 Wprowadzenie do J2EE

PHP: bazy danych, SQL, AJAX i JSON

Usługa TimerService

Uniwersytet Łódzki Wydział Matematyki i Informatyki, Katedra Analizy Nieliniowej. Wstęp. Programowanie w Javie 2. mgr inż.

Podstawy języka T-SQL : Microsoft SQL Server 2016 i Azure SQL Database / Itzik Ben-Gan. Warszawa, Spis treści

Aplikacja webowa w Javie szybkie programowanie biznesowych aplikacji Spring Boot + Vaadin

Enterprise JavaBeans

Administracja i programowanie pod Microsoft SQL Server 2000

AUREA BPM Oracle. TECNA Sp. z o.o. Strona 1 z 7

Java - tablice, konstruktory, dziedziczenie i hermetyzacja

Wzorce projektowe i architektura dla platformy Java EE

Replikacje. dr inż. Dziwiński Piotr Katedra Inżynierii Komputerowej. Kontakt:

Pod dwóch wprowadzających w koncepcję DDD częściach,

Baza danych sql. 1. Wprowadzenie. 2. Repozytaria generyczne

Administracja i programowanie pod Microsoft SQL Server 2000

Obiektowy PHP. Czym jest obiekt? Definicja klasy. Składowe klasy pola i metody

Podstawowe informacje o technologii Java Persistence API - przykład

Programowanie obiektowe

Iwona Milczarek, Małgorzata Marcinkiewicz, Tomasz Staszewski. Poznań,

Hurtownie danych wykład 5

Baza danych sql. 1. Wprowadzenie

Klasy i obiekty cz II

Automatyczne generowanie kodu. 4Developers, 26 marca 2010

Bezstanowe komponenty sesyjne i zdarzenia zwrotne

SYSTEM MONITORINGU PARAMETRÓW WĘZŁÓW PRZECHOWYWANIA DANYCH DLA PROJEKTU KRAJOWY MAGAZYN DANYCH PODRĘCZNIK DEWELOPERA

Projektowanie Aplikacji Internetowych Jarosław Kuchta. Wzorce projektowe warstwy biznesowej

Techniki programowania INP001002Wl rok akademicki 2018/19 semestr letni. Wykład 3. Karol Tarnowski A-1 p.

Java Zadanie 1. Aby poprawnie uruchomić aplikację desktopową, należy zaimplementować główną metodę zapewniającą punkt wejścia do programu.

Nowy powiew od Słońca: EJB 3.0. Copyright Piotr Kochański & Erudis,

Transkrypt:

JPA i Hibernate Dlaczego u mnie działa tak wolno? Sławomir Sobótka

Krótko o sobie... Twórca oprogramowania całościowe podejście Technologie Architektury Metodyki, podejścia, najlepsze praktyki Usability Trener i konsultant Java EE Inżynieria oprogramowania

Architektura Hibernate EntityManager i EntityManagerFactory zasada działania Pułapki wydajności JPA n+1 Select problem - wykrywanie i zapobieganie Pułapki Lazy loadingu oraz zbyt chciwego pobierania danych Nadmierne pobieranie danych Optymalne mapowanie encji Nadmiarowość pobierania danych Problemy z leniwym ładowaniem pól Hibernate cache niezastąpione rozwiązanie. Idea działania i konfiguracja Cache pierwszego poziomu Cache drugiego poziomu Mapowanie encji zorientowanie na cacheowanie Cache aplikacji EntityManager w trybie rozszerzonym Manualne opróżnianie sesji Agenda

Specyfika Java Persistence API Mapowanie Klasa-Tabele Klasa zawiera pola odpowiadające kolumnom Mapowanie przez XML lub Adnotacje Kod logiki? Generowanie SQL na podstawie mapowania zgodnie z wybranym dialektem SQL Śledzenie zmian encji (oraz encji zagregowanych) Mechanizm brudzenia Automatyczne utrwalanie zmian Wygodne mechanizmy wbudowane Lazy loading pobieranie zagregowanych encji w momencie pierwszego dostępu do nich Operacje kaskadowe operacje na całych grafach obiektów zagregowanych Uwaga na wydajność!!!

Mapowanie Aspekty praktyczne Agregacjie dwukierunkowe Stosować tylko gdy są uzasadnione biznesowo Enkapsulacja Są tworzone przez generatory Mogą ułatwiać pisanie zapytań Kolekcje Uwaga na ilość obiektów Uwaga na Lazy Loading i "n+1 select problem" FetchType - Uwaga na EAGER OneToOne ManyToOne

Mapowanie Aspekty praktyczne Mapowanie automatyczne Z bazy na encje generatory Naiwne mapowanie wszystkich agregacji Z encji na bazę feature implementacji JPA Rapid development Wygodne w fazie protopypowania Zweryfikować Ręczne Może wymagać tuningu bazy Całościowo - żmudne Tuning po automatycznym

Mapowanie zaawansowane Operacje kaskadowe @Entity @Entity public class Customer{ public class Customer{ @ManyToOne(cascade={ @ManyToOne(cascade={ CascadeType.PERSIST, CascadeType.PERSIST, CascadeType.REMOVE) CascadeType.REMOVE) private Address addr; private Address addr; JPA może wykonać daną operację zarówno na encji jak i na jej zagregowanych składowych Strategie operacji kaskadowych PERSIST MERGE również dodaje składowe REMOVE REFRESH - kosztowne! ALL Uwaga na sensowność tych operacji z biznesowego punktu widzenia Modyfikacja składowych ma sens gdy związek ma naturę kompozycji np: zamówienie i jego pozycje pozycja nie ma sensu bez zamówienia Uwaga na aspekt bezpieczeństwa!!! Przesyłanie grafów obiektów na server (PERSIST/MERGE)

Mapowanie zaawansowane Dodatkowe operacje kaskadowe Hibernate DELETE_ORPHAN Aplikuje się dla @OneToMany Kaskadowe usunięcie tych encji składowych, które usunięto z kolekcji encji głównej @Cascade({ @Cascade({ org.hibernate.annotations.cascadetype.save_update, org.hibernate.annotations.cascadetype.save_update, org.hibernate.annotations.cascadetype.delete_orphan) org.hibernate.annotations.cascadetype.delete_orphan)

Mapowanie zaawansowane FetchType - Polityka ładowania danych ORM wykorzystuje wzorzec Proxy pośrednik do encji modyfikacja ByteCode Adnotacje powiązań posiadają atrybut fetch o wartościach FetchType.EAGER Chciwie/łapczywie/gorliwie pobiera zagregowane encje JOIN w SQL Dodatkowe zapytanie! - n+1 Select Problem Domyślny dla zagregowanych encji @Entity @Entity @OneToOne public class User{ public class User{ @ManyToOne Address address; Address address; FetchType.LAZY Leniwe ładowanie danych gdy są potrzebne wywołanie get() Dodatkowe zapytanie! - n+1 Select Problem Domyślne dla kolekcji i obiektów LOB @OneToMany @ManyToMany @Lob @OneToOne(fetch=FetchType.LAZY) @OneToOne(fetch=FetchType.LAZY)

Architektura JPA Aplikacja Transaction Manager Persistence Unit Encja1 Zarządza EntityManager (Hibernate: Session) Tworzy EntityManagerFactory (Hibernate: SessionFactory) Encja2 L1 Cache L2 Cache Connection Pool DB

EntityManager Obiekt zarządzający encjami Jednostka pracy Śledzi encje Zarządza ich cyklem życia Synchronizuje je z bazą danych Jego utworzenie jest tanie Stanowi cache Współpracuje z Managerem transakcji (JTA) Stanowi bramę, przez którą encje komunikują się z bazą danych Lazy loading Po jego zamknięciu encje nie mogą korzystać już z LL

Cykl życia encji Źródło: Oracle http://download.oracle.com/docs/cd/b32110_01/web.1013/b28221/undejbs003.htm#cihcjggj

Entity Manager Wybrane, typowe wyjątki API PersistenceException klasa bazowa OptimisticLockException zmodyfikowano encję chronioną przez mechanizm wersjonowania EntityExistsException zapisujemy encję już zarządzaną EntityNotFoundException modyfikacja nieistniejącej encji NoResultException Query.singleResult() zwraca 0 danych NonUniqueResultException Query.singleResult() zwraca >1 danych org.hibernate.lazyinitializationexception Encja korzysta z Lazy Loading gdy EM jest już zamknięty Specyfikacja nie określa sposobu reagowania!

n+1 Select Problem Dowiesz się: Na czym polega ten problem wydajnościowy Z czego wynika Jak go wykrywać W jaki sposób można go unikać oraz niwelować dotkliwość

n+1 Select Problem Typowy przypadek List<User> user1 List<Address> address1 address2 user2 List<Address> address3 address4 address5 user3 List<Address> address6 Przy pomocy naiwnego zapytania pobieramy listę użytkowników Iterujemy po liście i pobieramy zagregowane obiekty @Entity @Entity public public class class User{ User{ @OneToMany @OneToMany private private List<Address> List<Address> addresses; addresses; List<User> List<User> users users = = entitymanager. entitymanager. createquery("select createquery("select u u FROM FROM User User u").getresultlist(); u").getresultlist(); for for (User (User u u : : users){ users){ for for (Address (Address a a : : u.getaddresses()){ u.getaddresses()){ //... //...

n+1 Select Problem Opis problemu List<User> user1 List<Address> address1 address2 user2 List<Address> address3 address4 address5 user3 List<Address> address6 Jeżeli sesja persystencji jest aktywna wówczas działa mechanizm Lazy Loading Dla każdego z N użytkowników wykonywane jest zapytanie o jego adresy (N razy adresy + 1 raz użytkownicy, w sumie N+1) Jeżeli sesja jest zamknięta wówczas w Hibernate dostajemy LazyInitalizationException

n+1 Select Problem Podejście (nie rozwiązanie) gorliwe List<User> user1 List<Address> address1 address2 user2 List<Address> address3 address4 address5 user3 List<Address> address6 Mapowanie kolekcji z fetch=fetchtype.eager Działa dal find() Dla zapytań o listę jet to jedynie sugestia wciąż możliwe n+1 zapytań Mapowanie Encji z FetchType.JOIN (tylko Hibernate) @LazyCollection (tylko Hibernate) FALSE EXTRA lazy, ale próba uniknięcia pobieranie WADY Usztywnienie mapowania Chciwe/łapczywe pobieranie nie jest zawsze pożądane @Entity @Entity public public class class User{ User{ @OneToMany(fetch=FetchType.EAGER) @OneToMany(fetch=FetchType.EAGER) private private List<Address> List<Address> addresses; addresses;

List<User> user1 List<Address> address1 address2 user2 List<Address> address3 address4 address5 user3 List<Address> n+1 Select Problem Rozwiązanie na szybko @org.hibernate.annotations.batchsize Pobierając element kolekcji pobiera x kolejnych na zapas WADY Specyfika Hibernate Działa na ślepo @Entity @Entity address6 public public class class User{ User{ @OneToMany @OneToMany @BatchSize(size=10) @BatchSize(size=10) private private List<Address> List<Address> addresses; addresses;

n+1 Select Problem Rozwiązanie właściwe List<User> user1 List<Address> address1 address2 user2 List<Address> address3 address4 address5 user3 List<Address> address6 Stworzenie rzetelnego zapytania z JOIN FETCH Zapytanie szyte na miarę - per Use Case Warto hermetyzować w DAO SELECT SELECT DISTINCT DISTINCT u FROM FROM User User u JOIN JOIN FETCH FETCH u.addresses Można próbować parametryzować ogólną metodę DAO doklejenie JOIN FETCH lepiej użyć Criteria API Criteria Criteria criteria criteria = = hibernatesession hibernatesession.createcriteria(user.class);.createcriteria(user.class); if if ( ){ ( ){ criteria.setfetchmode( addresses, criteria.setfetchmode( addresses, FetchModel.JOIN); FetchModel.JOIN);

n+1 Select Problem Wariant utajony Kolekcja (LAZY) jest iterowana przez komponent graficzny Listy h:datatable Przy klasycznym podejściu kontekst persystencji jest zamknięty gdy wykonuje się kod GUI LazyInitializationException Jest to sygnał, że model został źle zainicjowany Wygodne ulepszenia pozwalają jednak korzystać z Lazy Loading w warstwie widoku Open Session in View Transakcje w Seam

Wariant utajony jak to działa Transakcje globalne w Seam Brak jeżeli RESOURCE_LOCAL Page Actions Restore View Apply Request Validate Update Model Invoke App Render Resp Pierwsza transakcja Izolacja logiki biznesowej od renderingu Jeżeli rendering spowoduje błąd wówczas mimo tego zmiany biznesowe są utrwalone Render Response Lazy Loading w osobnej transakcji Jako całość Bez otwierania nowej transakcji per operacja LL Blokada FLUSH Rendering nie zmieni stanu bazy

Manualne kontrola konsoli <property <property name="show_sql">true</property> name="show_sql">true</property> <property <property name="format_sql">true</property> name="format_sql">true</property> n+1 Select Problem Wykrywanie log4j.logger.org.hibernate.type=debug log4j.logger.org.hibernate.type=debug Automatyczne Testy integracyjne mierzące ilość zapytań (API Statistics) Statistics Statistics stats stats = = sessionfactory.getstatistics() sessionfactory.getstatistics()

Pobieranie zbyt dużej ilości danych Dowiesz się: Jakie są spozoby na pobranie tylko tych danych, które są potrzebne Jak tworzyć własne paginatory tabel

Pobieranie zbyt dużej ilości danych Opis problemu Zapytania przekrojowe pobierają dane z wielu Encji (tabel), ale w konkretnym Use Case potrzeba zaledwie kilku kolumn z każdej z tabel 1. Obciążenie komunikacji z bazą danych 2. W razie zdalnego servisu narzut na serializację 3. Chwilowe obciążenie pamięci (niektóre pola mogą być ciężkie ) Przepakowanie z encji do DTO rozwiązuje jedynie problem #2

Pobieranie zbyt dużej ilości danych Rozwiązanie Lazy loading @Basic(fetch=FetchType.LAZY) @Basic(fetch=FetchType.LAZY) private private String String documentcontent; documentcontent; Hibernate: wymaga instrumentalizacji ByteCode Dodatkowe zapytanie gdy pole jednak jest potrzebne

Pobieranie zbyt dużej ilości danych Rozwiązanie Specyficzne klasy mapujące Specyficzne klasy mapujące zawierających potrzebne atrybuty Mnożenie bytów w domenie Brak wsparcia dla cache @MappedSuperClass @MappedSuperClass public public class class DocumentBase{ DocumentBase{ @Id @Id private private Long Long id; id; @Entity @Entity public public class class DocumentLite DocumentLite extends extends DocumentBase{ DocumentBase{ private private String String title; title; @Entity @Entity public public class class DocumentBig DocumentBig extends extends DocumentBase{ DocumentBase{ private private String String content; content;

Pobieranie zbyt dużej ilości danych Rozwiązanie Pobieranie DTO SELECT SELECT NEW NEW pakiet.userdto(u.id, u.name, u.name, u.address) FROM FROM User User u JOIN JOIN FETCH FETCH u.address Pobieranie danych wprost do Data Transfer Object Ograniczenia dla konstruktora

Pobieranie zbyt dużej ilości danych Rozwiązanie SQL Native SQL sess.createsqlquery("select sess.createsqlquery("select id, id, title title FROM FROM Documents").list(); Documents").list(); sess.createsqlquery("select sess.createsqlquery("select id, id, title title FROM FROM Documents") Documents").addEntity( d,.addentity( d, Document.class) Document.class).addJoin( d.author );.addjoin( d.author ); Hermetyzacja JDBC w DAO... Warto stworzyć wygodne klasy w stylu Spring JdbcTemplate hermetyzuje operacje na JDBC z uwzględnieniem transakcji JdbcDaoSupport klasa bazowa dla DAO (zawiera template) Command-query Separation...

Naiwna paginacja Problem: Działanie standardowych paginatorów w JSF (np. RichFaces) Przechowywanie całego wyniku zapytania w Sesji Wyświetlenie na GUI jedynie wycinka Zaletą jest cache danych (jednorazowy dostęp do bazy) Wadą jest zajęcie pamięci i transfer dużej ilości danych z bazy dla dużych list oraz gdy użytkownik nie przegląda kolejnych stron Rozwiązanie: Własna paginacja Implementacja własnego modelu rozszerzenie SerializableDataModel dziedziczący po ExtendedDataModel Kluczowa metoda walk(facescontext context, DataVisitor visitor, Range range, Object argument) Range określa wiersz początkowy i ilość potrzebnych wierszy Na tej podstawie można pobrać z bazy odpowiednią ilość wierszy

Count int int count count = = sess.createquery("from sess.createquery("from Document") Document").list().size();.list().size(); public int countdocuments(...){ public int countdocuments(...){ Criteria crit = createcriteria(...); Criteria crit = createcriteria(...); return (Integer) crit.setprojection(projections.rowcount()) return (Integer) crit.setprojection(projections.rowcount()).list().get(0);.list().get(0); public List<Document> searchdocuments(...){ public List<Document> searchdocuments(...){ Criteria crit = createcriteria(...); Criteria crit = createcriteria(...); return crit.list(); return crit.list(); private Criteria createcriteria(...){ private Criteria createcriteria(...){ Criteria criteria = hibernatesession.createcriteria(document.class); Criteria criteria = hibernatesession.createcriteria(document.class); return criteria; return criteria;

Hibernate Cache Dowiesz się: Jakie są poziomy Cache Jak jest skonfigurować Jak z nich korzystać Jak współpracować w środowisku, w którym inne systemy również modyfikują bazę danych

Architektura JPA Cache Aplikacja Transaction Manager Persistence Unit Encja1 Zarządza EntityManager (Hibernate: Session) Tworzy EntityManagerFactory (Hibernate: SessionFactory) Encja2 L1 Cache L2 Cache Query Cache Connection Pool DB

Rodzaje Cache Level 1 L1 Cache Encji pierwszego poziomu Domyślnie włączony w Hibernate Skojarzony z EntityManager (Session w Hibernate) Optymalizuje operacje EntityManager - w obrębie jednostki pracy Wielokrotne find() jeden SELECT wielokrotne merge() jeden UPDATE w SQL Silnik sprawdza istnienie encji w pierwszej kolejności w tym cache

Rodzaje Cache Level 2 L2 - Cache Encji lub kolekcji drugiego poziomu Skojarzony z EntityManagerFactory (SessionFactory w Hibernate) Optymalizuje dostęp do encji lub kolekcji na poziomie całej aplikacji find() odwołuje się do bazy tylko raz Silnik sprawdza istnienie encji w drugiej kolejności w tym cache W pierwszej kolejności jest sprawdzany L1

Rodzaje Cache Query Query Cache - Cache zapytań HQL Ma sens dla zapytań Wykonywanych często Z tymi samymi parametrami L2 cache musi być włączony

L2 Cache Konfiguracja <property <property name="hibernate.cache.provider_class"> name="hibernate.cache.provider_class"> org.hibernate.cache.ehcacheprovider org.hibernate.cache.ehcacheprovider </property> </property> <property <property name="hibernate.cache.use_second_level_cache" name="hibernate.cache.use_second_level_cache" value="true"/> value="true"/>

L2 Cache Implementacje Hashtable prosta implementacja w RAM EHCache (Easy Hibernate Cache) (org.hibernate.cache.ehcacheprovider) Szybka, lekka, łatwa w użyciu Wspiera cache read-only i read/write Działa w pamięci lub na dysku Nie obsługuje clusteringu OSCache (Open Symphony Cache) (org.hibernate.cache.oscacheprovider) Wydajna Wspiera cache read-only i read/write Działa w pamięci lub na dysku Podstawowa obsługa clusteringu SwarmCache (org.hibernate.cache.swarmcacheprovider) Oparta o klastry Wspiera cache read-only i nonstrict read/write Odpowiednia dla systemów z przewagą odczytów nad zapisami JBoss TreeCache (org.hibernate.cache.treecacheprovider) Wydajna Wspiera replikacje i transakcyjność cache

L2 Cache Strategie cache Read-only Najbardziej wydajna Encje są często czytane ale nigdy modyfikowane Słowniki Nonstrict read-write Encje są rzadko modyfikowane Read-write Większy narzut Encje są modyfikowane

L2 Cache przykład Encje i kolekcje @Entity @Entity @Cache( @Cache( usage usage = = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE) CacheConcurrencyStrategy.NONSTRICT_READ_WRITE) public public class class User User { { @OneToMany() @OneToMany() @Cache( @Cache( usage usage = = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE) CacheConcurrencyStrategy.NONSTRICT_READ_WRITE) public public List<Address> List<Address> addresses; addresses; Encja z listy również musi posiadać adnotację Cache

L2 Cache Wygaszanie Należy pamiętać o wygaszaniu gdy inny system modyfikuje dane sessionfactory.evict(user.class, userid); sessionfactory.evict(user.class); sessionfactory.evictcollection("user.addresses", userid); sessionfactory.evictcollection("user.adresses");

Cache kwerend Konfiguracja Należy zawsze stosować z L2 cache ponieważ Query cache nie przechowuje wartości Query cache przechowuje jedynie ID <property <property name="hibernate.cache.use_query_cache" name="hibernate.cache.use_query_cache" value="true"/> value="true"/>

Cache kwerend Przykłady @NamedQuery( @NamedQuery( name="allusers", name="allusers", query="from query="from User", User", hints={ hints={ @QueryHint( @QueryHint( name="org.hibernate.cacheable", name="org.hibernate.cacheable", value="true")) value="true")) @Entity @Entity public public class class User{.. User{.. hibernatesession.createquery( FROM User ) User ).setcacheable(true).list();.setcacheable(true).list(); Criteria Criteria criteria criteria = = hibernatesession.createcriteria(document.class); hibernatesession.createcriteria(document.class); criteria.setcacheable(true); criteria.setcacheable(true);

Cache kwerend Pułapka wyciek pamięci public public List<User> List<User> findusersbyaddress(address findusersbyaddress(address a){ a){ return return hibernatesession hibernatesession.createquery( FROM.createQuery( FROM User User u WHERE WHERE u.address u.address =? )? ).setparameter(0,.setparameter(0, a) a).setcacheable(true).setcacheable(true).list();.list(); Parametry kwerendy/kryteriów będą przechowywane wraz z zależnościami w cache kwerend Do czasu usunięcia danego wyniku z cache Parametry zapytania obiekty czy Id? Bardziej OO Zdalne wywołanie == narzut

Pobieranie encji gdy są rzeczywiście potrzebne User User user user = = (User)entityManager.getReference(User.class, (User)entityManager.getReference(User.class, 1L); 1L); Pobranie uchwytu - proxy do niezainicjowanego obiektu getreference może opóźnić pobranie encji do momentu, gdy będzie rzeczywiście użyta W razie braku encji o danym ID nie jest zwracany null lecz EntityNotFoundException przy pierwszym dostępie Zastosowanie Ciężkie wartości mogą ale muszą być potrzebne w algorytmie/aplikacji Encja jest potrzebna jedynie w celu ustawienia jako wartość innej encji Z poziomu technicznego: gdy potrzeba jedynie ID w poleceniu INSERT innej encji Niezainicjowana encja nie będzie miała sensu w stanie detached

Pobieranie danych dla widoku w getterach <h:datatable <h:datatable value= #{bean.users value= #{bean.users var= _user var= _user > > public public List<Users> List<Users> getusers(){ getusers(){ this.users this.users = = entitymanager... entitymanager... //lub //lub DAO/Serwis DAO/Serwis return return this.users; this.users; JSF woła gettery wielokrotnie (w kilku fazach obsługi żądania) Operacje na bazie danych zostaną wykonane wiele razy Model dla prezentacji należy inicjować wcześniej Styl PULL metoda obsługująca akcję Styl PUSH inicjalizacja obiektu @PostConstruct - JSR-250 (Common Annotation for Java Platform) @Create Seam @Factory gdy obiekt nie istnieje @Unwrapp za każdym razem

Konwersacje Wstęp do aplikacyjnego cache Dowiesz się: Na czym polega mechanizm konwersacji W jakiś sposób Seam zarządza EntityManagerem w konwersacji Poznasz tryb rozszerzony EntityManagera Poznasz mechanizm ręcznego opróżnainia EntityManagera Poznasz zależność EntityManagera od cyklu życia transakcji Dowiesz się na jakiej zasadzie działa dołączania odłączonych Encji do EntityManagera Jak konwersacje współpracują z Kontekstem Persystencji działającym w trybie rozszerzonym Dowiesz się jak wykorzystać wymienione mechanizmy Zrozumiesz na jakiej zasadzie działa cache aplikacyjny

Zasięg Komponentów (przykład Seam) Access Stateless Method Event(Request) Event Event Event Page (Continuation) Conversation Session Session Business Process Restart Application

Konwersacje Unit of work Może przekładać się na Use Case Przechowuje stan pomiędzy żądaniami Posiada własny ID, dzięki któremu jest rozróżnialny w zakładkach Stanowi cache procesu optymalizacja dostępu do danych Mogą przechowywać Dane nieutrwalane (transient) Encja odłączone (detached) Encja zarządzane (managed) Zasoby EntityManager również w stanie rozszerzonym

Persistence Context Założenia EntityManager (Session w Hibenrate) Został zaprojektowany tak aby istnieć przez dłuższy czas Dłuższy niż transakcja Nie należy utożsamiać go z chwilowym połączeniem z bazą EM nie jest threadsafe Nie należy go współdzielić pomiędzy równoległymi wątkami

Persistence Context Zarządzanie Zarządzanie przez kontener JEE EntityManager jest wstrzykiwany do SFSB Zasięg życia EM jest taki jak posiadającego go komponentu Skomplikowane reguły propagacji Zarządzanie przez Seam Wstrzykiwanie do POJO/EJB (@In) EM jest takim samym komponentem jak pozostałe Znajduje się w kontekście konwersacji Również w Konwersacji tymczasowej Obejmującej request Lazy Loading działa w warstwie widoku:) Z tego powodu należy śledzić logi!!! Zasięg życia konwersacji Bez związku z zasięgiem innego komponentu Możliwość wstrzykiwania do wielu komponentów bez ograniczeń

Persistence Context Tryby pracy Tryb transakcyjny (domyślny dla JEE) Zasięg sesji EntityManagera jest taki sam jak transakcji JTA Zwykle jest to wywołanie jednej metody EJB Czyli jeden request (ale tylko w warstwie biznesowej) Po zamknięciu Encją są w stanie Detached Tryb EXTENDED (domyślny w Seam) Zasięg sesji EntityManagera jest szerszy... Encje są cały czas w stanie Managed Redukcja komunikacji z bazą - ponowne odczyty (merge) Działający Lazy Loading Należy pamiętać o Optimistic Locking (@Version)! Działa jako naturalny Cache (L1)

Tryb rozszerzony w JEE Przykład @Stateful public public class class UserAgentBean implements UserAgent { @PersistenceContext( type type = PersistenceContextType.EXTENDED) private private EntityManager em; em;

EntityManager Tryb transakcyjny Request Request Response Response Lazy Loading XLazy Loading Encja (graf) W sesji X Lazy Loading Metoda biznesowa Rendering Transakcja EntityManager flush Metoda biznesowa Rendering Transakcja EntityManager flush

EntityManager Tryb rozszerzony Encja (graf) W sesji Request Lazy Loading Lazy Loading Response Request Lazy Loading Response Metoda biznesowa Rendering Metoda biznesowa Rendering Transakcja EntityManager Transakcja flush flush

Transakcje globalne Brak jeżeli RESOURCE_LOCAL Page Actions Restore View Apply Request Validate Update Model Invoke App Render Resp Pierwsza transakcja Izolacja logiki biznesowej od renderingu Jeżeli rendering spowoduje błąd wówczas mimo tego zmiany biznesowe są utrwalone Render Response Lazy Loading w osobnej transakcji Jako całość Bez otwierania nowej transakcji per operacja LL Blokada FLUSH Rendering nie zmieni stanu bazy

Transakcje aplikacyjne Wstęp Kontekst perystencji w trybie rozszerzonym rozciąga się na kilka requestów Podczas każdego z requestów tworzona jest transakcja Kontekst perystencji jest do niej podczepiany Po każdorazowym zamknięciu transakcji następuje flush kontekstu perystencji zapis zmienionych (dirty) Encji Ponieważ w JPA wyspecyfikowano dwie polityki AUTO kontekst opróżnia się w momentach, które uzna za najbardziej stosowne COMMIT kontekst opróżnia się przy komitowaniu transakcji Skutek Mimo że konwersacja trwa wiele requestów Po każdym z nim zmienia się stan bazy W dalszej części konwersacji może wystąpić błąd Ale dane są już zapisane

Transakcje aplikacyjne Zastosowanie Hibernate Istnieje możliwość odroczenia opróżniania kontekstu persysyencji Do momentu wywołania metody flush() Nawet mimo tego, że transakcja jest zamykana Specyfika Hibernate Session jako kontekst persystencji Lub nawet jako implementację JPA (używając EntityManager) Rozpoczynając konwersację należy włączyć ręczny tryb opróżniania Wówczas w każdym request kontekst jest podłączany do nowej transakcji Działa LL Ale na zakończenie transakcji kontekst nie zapisuje zmian Zrobi to dopiero po wywołaniu flush() Taki kontekst działa jako cache poleceń zapisu danych Czyli rodzaj transakcji - lecz nie bazodanowej a aplikacyjnej

EntityManager Tryb rozszerzony + Manual Flush Encja (graf) W sesji Request Lazy Loading Lazy Loading Response Request Lazy Loading Response Metoda biznesowa Rendering Metoda biznesowa Rendering Transakcja EntityManager Transakcja Flush (manual)

Transakcje aplikacyjne Przykład @Name("userWizardAction")@Scope(ScopeType.CONVERSATION) @Name("userWizardAction")@Scope(ScopeType.CONVERSATION) @Transactional @Transactional public public class class UserWizardAction UserWizardAction implements implements Serializable Serializable { { @In @In private private EntityManager EntityManager entitymanager; entitymanager; @Out @Out private private User User user; user; @Begin(flushMode @Begin(flushMode = = FlushModeType.MANUAL) FlushModeType.MANUAL) public public void void adduser() adduser() { { user user = =...... entitymanager.persist(user); entitymanager.persist(user); public public String String addbasicdata() addbasicdata() { {...... return return "next"; "next"; @End @End public public String String save() save() { { entitymanager.flush(); entitymanager.flush(); return return "saved"; "saved";

Dziękuję za uwagę więcej... http://art-of-software.blogspot.com slawomir.sobotka@bottega.com.pl Sławomir Sobótka

Photo Credits http://merlin.pl/spiewajacy-zolw_fisher-price,images_big,6,fpm4925.jpg