Tag: SqlResultSetMapping
krása leží v oku pozorovatele. Stejně tak „snadné“:
další informace o mapování SQL Result Set a snadné zpracování výsledků nativních dotazů: http://t.co/WH4BTlClIP #JPA # Java # JavaEE
– Thorben Janssen (@thjanssen123) Duben 15, 2015
Thorben píše velmi dobré a užitečné články o JPA a nedávno zahájil vynikající sérii o nových funkcích JPA 2.1. Mezi které patří: mapování sady výsledků. Mapování sady výsledků můžete znát z webových stránek, jako je CTMMC, nebo annotatiomania.com. tento postup mapování můžeme shrnout takto:
a) definujte mapování
@SqlResultSetMapping( name = "BookAuthorMapping", entities = { @EntityResult( entityClass = Book.class, fields = { @FieldResult(name = "id", column = "id"), @FieldResult(name = "title", column = "title"), @FieldResult(name = "author", column = "author_id"), @FieldResult(name = "version", column = "version")}), @EntityResult( entityClass = Author.class, fields = { @FieldResult(name = "id", column = "authorId"), @FieldResult(name = "firstName", column = "firstName"), @FieldResult(name = "lastName", column = "lastName"), @FieldResult(name = "version", column = "authorVersion")})})
výše uvedené mapování je spíše přímočaré. Určuje, jak mají být sloupce databáze mapovány na pole entit a na entity jako celek. Pak dáte tomuto mapování název ("BookAuthorMapping"
), který pak můžete znovu použít v celé aplikaci, např. s nativními dotazy JPA.
konkrétně se mi líbí skutečnost, že Thorben pak píše:
pokud se vám nelíbí přidat do entity takový obrovský blok anotací, můžete také definovat mapování v souboru XML
… takže jsme zpět k nahrazení obrovských bloků anotací obrovskými bloky XML-technikou, kterou se mnozí z nás chtěli vyhnout používání anotací… :- )
b) použijte mapování
jakmile je mapování staticky definováno na nějakém typu Java, můžete tyto entity načíst použitím výše uvedeného BookAuthorMapping
List<Object> results = this.em.createNativeQuery( "SELECT b.id, b.title, b.author_id, b.version, " + " a.id as authorId, a.firstName, a.lastName, " + " a.version as authorVersion " + "FROM Book b " + "JOIN Author a ON b.author_id = a.id", "BookAuthorMapping").getResultList();results.stream().forEach((record) -> { Book book = (Book)record; Author author = (Author)record;});
Všimněte si, jak si stále musíte pamatovat typy Book
a Author
a odevzdat explicitně, protože k ničemu nejsou připojeny žádné ověřitelné informace o typu.
definice „komplexu“
nyní článek tvrdí, že se jedná o „komplexní“ mapování, a bezpochyby bych souhlasil. Tento velmi jednoduchý dotaz pouze s jednoduchým spojením již spouští takový anotační nepořádek, pokud chcete skutečně mapovat své entity prostřednictvím JPA. Nechcete vidět anotace thorbenova mapování, jakmile budou dotazy trochu složitější. A pamatujte, @SqlResultSetMapping
je o mapování (nativní!) SQL výsledky, takže už nejsme v object-graph-persistence zemi, jsme v SQL zemi, kde hromadné načítání, denormalizace, agregace, a další“ fantazie “ SQL věci je král.
problém je zde:
Java 5 představil anotace. Anotace byly původně určeny k použití jako „umělé modifikátory“, tj. static
, final
, protected
(zajímavé je, že Ceylon zná pouze anotace, žádné modifikátory). To dává smysl. Návrháři jazyka Java by mohli zavést nové modifikátory / „klíčová slova“, aniž by porušili stávající kód – protože“ skutečná “ klíčová slova jsou vyhrazená slova, která je těžké zavést v jazyce. Pamatujete si enum
?
takže dobré případy použití anotací (a je jich jen málo) jsou:
@Override
-
@Deprecated
(ačkoli, atribut Komentáře by byl fantastický) @FunctionalInterface
JPA (a další Java EE API, stejně jako jaro) se úplně zbláznili při používání anotací. Opakujte po mně:
žádný jazyk
@Before
nebo@After
Java někdy zneužíval anotace stejně jako Java(myšlenka @Before / @After byla lennoffova, na Redditu)
při čtení výše uvedeného je ve mně silné déjà vu. Pamatujete si následující?
žádný jazyk před nebo po Java nikdy zneužil kontrolované výjimky, stejně jako Java
všichni budeme hluboce litovat Java anotací do roku 2020.
anotace jsou velké bradavice v systému typu Java. Mají extrémně omezené oprávněné použití a to, co v dnešní době děláme vývojáři Java Enterprise, není absolutně v mezích „oprávněného“. Zneužíváme je pro věci, na které bychom měli psát kód.
zde je návod, jak spustit stejný dotaz s jOOQ (nebo jiné API, které využívá generika a typ bezpečnost pro SQL):
Book b = BOOK.as("b");Author a = AUTHOR.as("a");DSL.using(configuration) .select(b.ID, b.TITLE, b.AUTHOR_ID, b.VERSION, a.ID, a.FIRST_NAME, a.LAST_NAME, a.VERSION) .from(b) .join(a).on(b.AUTHOR_ID.eq(a.ID)) .fetch() .forEach(record -> { BookRecord book = record.into(b); AuthorRecord author = record.into(a); });
tento příklad kombinuje anotace JPA 2.1 a dotazování. Všechny meta informace o předpokládaných „entitách“ jsou již obsaženy v dotazu a tedy v Result
, který je vytvořen metodou fetch()
. Ale na tom opravdu nezáleží, jde o to, že tento lambda výraz …
record -> { BookRecord book = record.into(b); AuthorRecord author = record.into(a);}
… může to být cokoli chcete! Stejně jako sofistikovanější příklady, které jsme ukázali v předchozích příspěvcích na blogu:
- žádné další potřeba ORMs
- Transformujte data SQL do grafů pomocí Jooq a JavaFX
mapování lze definovat ad-hoc, za běhu, pomocí funkcí. Funkce jsou ideální mapovače, protože přijímají vstup, produkují výstup a jsou zcela bez státní příslušnosti. A nejlepší na funkcích v Javě 8 je, že jsou kompilovány kompilátorem Java a mohou být použity k zadání kontroly mapování. Objektům můžete přiřadit funkce, což vám umožní znovu použít funkce, když lze daný mapovací algoritmus použít několikrát.
ve skutečnosti je samotná klauzule SQL SELECT
takovou funkcí. Funkce, která transformuje vstupní n-tice / řádky do výstupních n-tice / řádky, a můžete přizpůsobit tuto funkci za běhu pomocí dalších výrazů.
neexistuje absolutně žádný způsob, jak zadat kontrolu v předchozím příkazu JPA 2.1 nativního SQL a @SqlResultSetMapping
příklad. Představte si změnu názvu sloupce:
List<Object> results = this.em.createNativeQuery( "SELECT b.id, b.title as book_title, " + " b.author_id, b.version, " + " a.id as authorId, a.firstName, a.lastName, " + " a.version as authorVersion " + "FROM Book b " + "JOIN Author a ON b.author_id = a.id", "BookAuthorMapping").getResultList();
všimli jste si rozdílu? Sloupec b.title
byl přejmenován na book_title
. V řetězci SQL. Který vybuchne v době běhu! Jak si pamatovat, že se musíte také přizpůsobit
@FieldResult(name = "title", column = "title")
… Chcete-li být
@FieldResult(name = "title", column = "book_title")
naopak, jak si pamatovat, že jakmile přejmenujete column
ve vašem @FieldResult
, budete muset také zkontrolovat, kde se používá tento "BookAuthorMapping"
, a také změnit názvy sloupců v těchto dotazech.
@SqlResultSetMapping( name = "BookAuthorMapping", ...)
anotace jsou zlé
můžete nebo nemusíte souhlasit s některými z výše uvedených. Můžete nebo nemusí líbit jOOQ jako alternativu k JPA, to je naprosto v pořádku. Ale je opravdu těžké nesouhlasit s tím, že:
- Java 5 představil velmi užitečné anotace
- Java EE / Spring těžce zneužil tyto anotace nahradit XML
- nyní máme paralelní vesmír typový systém v Javě
- tento paralelní vesmír Typ systém je zcela k ničemu, protože kompilátor nemůže introspekci
- Java SE 8 zavádí funkční programování a spousta typu inference
- Java se 9-10 představí více úžasné jazykové funkce
- nyní je jasné, že to, co bylo konfigurace (XML nebo anotace) by měl být kód na prvním místě
- JPA 2.1 se stal novým EJB 2.0: zastaralým
jak jsem řekl. Těžko nesouhlasit. Nebo jinými slovy:
kód je mnohem lepší při vyjadřování algoritmů než konfigurace
osobně jsem se s Thorbenem setkal několikrát na konferencích. Toto chvástání zde nebylo myšleno osobně, Thorbene: -) vaše články o JPA jsou velmi zajímavé. Pokud vy čtenáři tohoto článku používáte JPA, podívejte se na thorbenův blog: http://www.thoughts-on-java.org.
mezitím bych rád Thorbena nominoval na respektovaný titul „Annotatiomaniac roku 2015“
Write a Reply or Comment