Představte si, že máte nástroj, který dokáže automaticky detekovat problémy s výkonem JPA a hibernace. Hypersistence Optimizer je ten nástroj!
Úvod
pokud vás zajímá, proč a kdy byste měli používat JPA nebo hibernace, pak vám tento článek poskytne odpověď na tuto velmi častou otázku. Protože jsem viděl tuto otázku položenou velmi často na kanálu/r / java Reddit, rozhodl jsem se, že stojí za to napsat hloubkovou odpověď o silných a slabých stránkách JPA a Hibernate.
ačkoli je JPA standardem od prvního vydání v roce 2006, není to jediný způsob, jak implementovat vrstvu pro přístup k datům pomocí Java. Budeme diskutovat o výhodách a nevýhodách používání JPA nebo jiných populárních alternativ.
proč a kdy byl JDBC vytvořen
v roce 1997, Java 1.1 představil API JDBC (Java Database Connectivity), které bylo na svou dobu velmi revoluční, protože nabízelo možnost zapsat vrstvu pro přístup k datům jednou pomocí sady rozhraní a spustit ji na jakékoli relační databázi, která implementuje rozhraní JDBC API, aniž by bylo nutné měnit kód aplikace.
JDBC API nabízí rozhraní Connection
pro řízení hranic transakcí a vytváření jednoduchých příkazů SQL pomocí API Statement
nebo připravených příkazů, které umožňují vázat hodnoty parametrů pomocí API PreparedStatement
.
takže za předpokladu, že máme post
databázovou tabulku a chceme vložit 100 řádků, můžeme tohoto cíle dosáhnout pomocí JDBC:
int postCount = 100;int batchSize = 50;try (PreparedStatement postStatement = connection.prepareStatement(""" INSERT INTO post ( id, title ) VALUES ( ?, ? ) """)) { for (int i = 1; i <= postCount; i++) { if (i % batchSize == 0) { postStatement.executeBatch(); } int index = 0; postStatement.setLong( ++index, i ); postStatement.setString( ++index, String.format( "High-Performance Java Persistence, review no. %1$d", i ) ); postStatement.addBatch(); } postStatement.executeBatch();} catch (SQLException e) { fail(e.getMessage());}
i když jsme využili víceřádkových textových bloků a bloků try-with-resources k odstranění volání PreparedStatement
close
, implementace je stále velmi podrobná. Všimněte si, že parametry vazby začínají od 1
, ne od 0
, jak byste mohli být zvyklí z jiných známých API.
Chcete-li načíst prvních 10 řádků, mohli bychom spustit dotaz SQL pomocí PreparedStatement
, který vrátí ResultSet
představující výsledek dotazu založený na tabulce. Protože však aplikace používají hierarchické struktury, jako JSON nebo DTOs, aby reprezentovaly asociace rodič-dítě, většina aplikací potřebovala transformovat JDBC ResultSet
do jiného formátu ve vrstvě pro přístup k datům, jak ukazuje následující příklad:
int maxResults = 10;List<Post> posts = new ArrayList<>();try (PreparedStatement preparedStatement = connection.prepareStatement(""" SELECT p.id AS id, p.title AS title FROM post p ORDER BY p.id LIMIT ? """)) { preparedStatement.setInt(1, maxResults); try (ResultSet resultSet = preparedStatement.executeQuery()) { while (resultSet.next()) { int index = 0; posts.add( new Post() .setId(resultSet.getLong(++index)) .setTitle(resultSet.getString(++index)) ); } }} catch (SQLException e) { fail(e.getMessage());}
opět je to nejhezčí způsob, jak bychom to mohli napsat pomocí JDBC, protože používáme textové bloky, vyzkoušejte zdroje a plynulé API pro vytváření objektů Post
.
nicméně JDBC API je stále velmi podrobné a co je důležitější, postrádá mnoho funkcí, které jsou vyžadovány při implementaci moderní vrstvy pro přístup k datům, jako například:
- způsob, jak načíst objekty přímo ze sady výsledků dotazu. Jak jsme viděli ve výše uvedeném příkladu, musíme iterovat
ReusltSet
a extrahovat hodnoty sloupců, abychom nastavili vlastnosti objektuPost
. - transparentní způsob dávkových příkazů, aniž byste museli přepisovat přístupový kód k datům při přechodu z výchozího režimu bez dávkování na použití dávkování.
- podpora optimistického zamykání
- stránkovací API, které skrývá základní syntaxi dotazu Top-N A Next-N specifickou pro databázi
proč a kdy byl vytvořen hibernace
v roce 1999 vydal Sun J2EE (Java Enterprise Edition), který nabídl alternativu k JDBC, nazvaný Entity Beans.
vzhledem k tomu, že fazole Entity byly notoricky pomalé, komplikované a těžkopádné, v roce 2001 se Gavin King rozhodl vytvořit rámec ORM, který by mohl mapovat databázové tabulky na POJOs (prosté staré objekty Java), a tak se zrodil hibernace.
být lehčí než entita fazole a méně podrobný než JDBC, Hibernate rostl více a více populární, a to brzy se stal nejpopulárnější Java persistence framework, vítězství nad JDO, iBatis, Oracle TopLink, a Apache Cayenne.
proč a kdy byl vytvořen JPA?
Poučení z úspěchu projektu Hibernate se platforma Java EE rozhodla standardizovat způsob hibernace a Oracle TopLink, a tak se zrodil JPA (Java Persistence API).
JPA je pouze specifikace a nemůže být použita samostatně, poskytuje pouze sadu rozhraní, která definují standardní persistence API, které je implementováno poskytovatelem JPA, jako je hibernace, EclipseLink nebo OpenJPA.
při použití JPA je třeba definovat mapování mezi databázovou tabulkou a přidruženým objektem entity Java:
@Entity@Table(name = "post")public class Post { @Id private Long id; private String title; public Long getId() { return id; } public Post setId(Long id) { this.id = id; return this; } public String getTitle() { return title; } public Post setTitle(String title) { this.title = title; return this; }}
poté můžeme přepsat předchozí příklad, který uložil ZÁZNAMY 100 post
, vypadá takto:
for (long i = 1; i <= postCount; i++) { entityManager.persist( new Post() .setId(i) .setTitle( String.format( "High-Performance Java Persistence, review no. %1$d", i ) ) );}
Chcete-li povolit dávkové vložky JDBC, stačí zadat jednu konfigurační vlastnost:
<property name="hibernate.jdbc.batch_size" value="50"/>
jakmile je tato vlastnost poskytnuta, hibernace může automaticky přepnout z non-dávkování na dávkování bez nutnosti jakékoli změny přístupového kódu k datům.
a pro načtení prvních 10 řádků post
můžeme spustit následující dotaz JPQL:
int maxResults = 10;List<Post> posts = entityManager.createQuery(""" select p from post p order by p.id """, Post.class).setMaxResults(maxResults).getResultList();
pokud to porovnáte s verzí JDBC, uvidíte, že použití JPA je mnohem jednodušší.
výhody a nevýhody použití JPA a hibernace
JPA obecně a zejména hibernace nabízejí mnoho výhod.
- můžete načíst entity nebo DTOs. Můžete dokonce načíst hierarchickou projekci DTO rodič-dítě.
- můžete povolit dávkování JDBC beze změny přístupového kódu k datům.
- máte podporu pro optimistické zamykání.
- máte pesimistickou zamykací abstrakci, která je nezávislá na základní syntaxi specifické pro databázi, takže můžete získat zámek pro čtení a zápis nebo dokonce zámek pro přeskočení.
- máte rozhraní API nezávislé na databázi.
- můžete zadat
List
hodnot klauzuli v dotazu, jak je vysvětleno v tomto článku. - můžete použít silně konzistentní řešení ukládání do mezipaměti, které vám umožní vyložit primární uzel, který lze pro REA-write transakce volat pouze svisle.
- máte vestavěnou podporu pro protokolování auditu přes Hibernate Envers.
- máte vestavěnou podporu pro multitenancy.
- počáteční skript schématu můžete vygenerovat z mapování entit pomocí nástroje hibernace hbm2ddl, který můžete dodat do nástroje pro automatickou migraci schématu, jako je Flyway.
- nejen, že máte svobodu provádění jakéhokoli nativního dotazu SQL, ale můžete použít SqlResultSetMapping k transformaci JDBC
ResultSet
na entity JPA nebo DTOs.
nevýhody použití JPA a hibernace jsou následující:
- zatímco Začínáme s JPA je velmi snadné, stát se odborníkem vyžaduje značné časové investice, protože kromě čtení jeho příručky se stále musíte naučit, jak fungují databázové systémy, standard SQL a specifickou příchuť SQL používanou databází vztahů s projektem.
- existuje několik méně intuitivních chování, které by mohly překvapit začátečníky, jako je příkaz flush operation.
- API kritérií je poměrně podrobné, takže pro snadnější psaní dynamických dotazů musíte použít nástroj, jako je Codota.
celková komunita a populární integrace
JPA a hibernace jsou velmi populární. Podle zprávy 2018 Java ecosystem report od Snyk, Hibernate používá 54% každého vývojáře Java, který interaguje s relační databází.
tento výsledek může být podpořen Trendy Google. Mybatis, QueryDSL a jOOQ), můžeme vidět, že JPA je mnohokrát populárnější a nevykazuje žádné známky ztráty své dominantní pozice na trhu.
být tak populární přináší mnoho výhod, jako například:
- integrace jarních dat JPA funguje jako kouzlo. Ve skutečnosti je jedním z největších důvodů, proč jsou JPA a hibernace tak populární, protože Spring Boot používá jarní Data JPA, která zase používá hibernace v zákulisí.
- pokud máte nějaký problém, existuje velká šance, že tyto 30k hibernace související StackOverflow odpovědi a 16k JPA související StackOverflow odpovědi vám poskytne řešení.
- k dispozici jsou 73K hibernace tutoriály. Pouze můj web sám nabízí více než 250 výukových programů JPA a hibernace, které vás naučí, jak vytěžit maximum z JPA a hibernace.
- existuje mnoho video kurzů, které můžete použít, stejně jako můj vysoce výkonný Java Persistence video kurz.
- existuje více než 300 knih o hibernaci na Amazonu, z nichž jedna je také Moje vysoce výkonná kniha Java Persistence.
alternativy JPA
jednou z největších věcí na ekosystému Java je množství vysoce kvalitních rámců. Pokud JPA a hibernace nejsou vhodné pro váš případ použití, můžete použít některý z následujících rámců:
- mybatis, což je velmi lehký SQL dotaz Mapper framework.
- QueryDSL, který umožňuje vytvářet SQL, JPA, Lucene a MongoDB dotazy dynamicky.
- jOOQ, který poskytuje Java metamodel pro podkladové tabulky, uložené procedury a funkce a umožňuje vytvářet SQL dotaz dynamicky pomocí velmi intuitivního DSL a typově bezpečným způsobem.
takže použijte, co vám nejlépe vyhovuje.
online workshopy
pokud se vám tento článek líbil, vsadím se, že se vám bude líbit můj nadcházející 4denní x 4 hodinový vysoce výkonný online Workshop Java Persistence
závěr
v tomto článku jsme viděli, proč byl vytvořen JPA a kdy byste jej měli použít. Zatímco JPA přináší mnoho výhod, máte mnoho dalších vysoce kvalitních alternativ k použití, pokud JPA a hibernace nefungují nejlépe pro vaše aktuální požadavky na aplikaci.
a někdy, jak jsem vysvětlil v tomto bezplatném vzorku mé vysoce výkonné knihy Java Persistence, nemusíte si ani vybírat mezi JPA nebo jinými rámci. Můžete snadno kombinovat JPA s rámcem, jako je jOOQ, abyste získali to nejlepší z obou světů.