日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

为JPA的本机查询API键入安全查询

發布時間:2023/12/3 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 为JPA的本机查询API键入安全查询 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

當您使用JPA時-有時-JPQL無法解決問題,您將不得不使用本機SQL。 從一開始,像Hibernate這樣的ORM就為這些情況保留了一個開放的“后門”,并為Spring的JdbcTemplate , Apache DbUtils或jOOQ提供了類似的API,用于純SQL 。 這很有用,因為您可以繼續將ORM用作數據庫交互的單個入口點。

但是,使用字符串連接編寫復雜的動態SQL既繁瑣又容易出錯,并且是SQL注入漏洞的門戶。 使用像jOOQ這樣的類型安全的API會非常有用,但是您可能會發現僅在10-15個本機查詢中就很難在同一應用程序中維護兩個不同的連接,事務和會話模型。

但事實是:

您可以將jOOQ用于JPA本機查詢!

確實如此! 有幾種方法可以實現此目的。

提取元組(即Object [])

最簡單的方法將不會利用JPA的任何高級功能,而只是為您獲取JPA的本機Object[]形式的元組。 假設這個簡單的實用方法:

public static List<Object[]> nativeQuery(EntityManager em, org.jooq.Query query ) {// Extract the SQL statement from the jOOQ query:Query result = em.createNativeQuery(query.getSQL());// Extract the bind values from the jOOQ query:List<Object> values = query.getBindValues();for (int i = 0; i < values.size(); i++) {result.setParameter(i + 1, values.get(i));}return result.getResultList(); }

使用API

這就是您以最簡單的形式橋接這兩個API所需要的,以通過EntityManager運行“復雜”查詢:

List<Object[]> books = nativeQuery(em, DSL.using(configuration).select(AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME, BOOK.TITLE).from(AUTHOR).join(BOOK).on(AUTHOR.ID.eq(BOOK.AUTHOR_ID)).orderBy(BOOK.ID));books.forEach((Object[] book) -> System.out.println(book[0] + " " + book[1] + " wrote " + book[2]));

同意的結果中沒有很多類型安全性,因為我們只得到一個Object[] 。 我們期待著將來支持Scala或Ceylon之類的元組(甚至記錄)類型的Java。

因此,更好的解決方案可能是:

獲取實體

假設您具有以下非常簡單的實體:

@Entity @Table(name = "book") public class Book {@Idpublic int id;@Column(name = "title")public String title;@ManyToOnepublic Author author; }@Entity @Table(name = "author") public class Author {@Idpublic int id;@Column(name = "first_name")public String firstName;@Column(name = "last_name")public String lastName;@OneToMany(mappedBy = "author")public Set<Book> books; }

并假設,我們將添加一個附加的實用程序方法,該方法還將Class引用傳遞給EntityManager :

public static <E> List<E> nativeQuery(EntityManager em, org.jooq.Query query,Class<E> type ) {// Extract the SQL statement from the jOOQ query:Query result = em.createNativeQuery(query.getSQL(), type);// Extract the bind values from the jOOQ query:List<Object> values = query.getBindValues();for (int i = 0; i < values.size(); i++) {result.setParameter(i + 1, values.get(i));}// There's an unsafe cast here, but we can be sure// that we'll get the right type from JPAreturn result.getResultList(); }

使用API

現在這相當靈活,只需將jOOQ查詢放入該API并從中獲取JPA實體-兩者兼有,因為您可以輕松地從獲取的實體中添加/刪除嵌套集合,就好像您是通過JPQL來獲取它們一樣:

List<Author> authors = nativeQuery(em,DSL.using(configuration).select().from(AUTHOR).orderBy(AUTHOR.ID) , Author.class); // This is our entity class hereauthors.forEach(author -> {System.out.println(author.firstName + " " + author.lastName + " wrote");books.forEach(book -> {System.out.println(" " + book.title);// Manipulate the entities here. Your// changes will be persistent!}); });

獲取實體結果

如果您比較敢于冒險并且對注釋有一種奇怪的喜好 ,或者只是想在休假前給同事開個玩笑,還可以使用JPA的javax.persistence.SqlResultSetMapping 。 想象以下映射聲明:

@SqlResultSetMapping(name = "bookmapping",entities = {@EntityResult(entityClass = Book.class,fields = {@FieldResult(name = "id", column = "b_id"),@FieldResult(name = "title", column = "b_title"),@FieldResult(name = "author", column = "b_author_id")}),@EntityResult(entityClass = Author.class,fields = {@FieldResult(name = "id", column = "a_id"),@FieldResult(name = "firstName", column = "a_first_name"),@FieldResult(name = "lastName", column = "a_last_name")})} )

本質上,以上聲明將數據庫列( @SqlResultSetMapping -> entities -> @EntityResult -> fields -> @FieldResult -> column )映射到實體及其相應屬性。 使用這種強大的技術,您可以從任何類型的SQL查詢結果中生成實體結果。

同樣,我們將創建一個小的實用工具方法:

public static <E> List<E> nativeQuery(EntityManager em, org.jooq.Query query,String resultSetMapping ) {// Extract the SQL statement from the jOOQ query:Query result = em.createNativeQuery(query.getSQL(), resultSetMapping);// Extract the bind values from the jOOQ query:List<Object> values = query.getBindValues();for (int i = 0; i < values.size(); i++) {result.setParameter(i + 1, values.get(i));}// This implicit cast is a lie, but let's risk itreturn result.getResultList(); }

請注意, 上面的API使用了anti-pattern ,在這種情況下可以使用,因為JPA首先不是類型安全的API。

使用API

現在,再次,您可以通過上述API將類型安全的jOOQ查詢傳遞給EntityManager ,并傳遞SqlResultSetMapping的名稱,如下SqlResultSetMapping :

List<Object[]> result = nativeQuery(em,DSL.using(configuration.select(AUTHOR.ID.as("a_id"),AUTHOR.FIRST_NAME.as("a_first_name"),AUTHOR.LAST_NAME.as("a_last_name"),BOOK.ID.as("b_id"),BOOK.AUTHOR_ID.as("b_author_id"),BOOK.TITLE.as("b_title")).from(AUTHOR).join(BOOK).on(BOOK.AUTHOR_ID.eq(AUTHOR.ID)).orderBy(BOOK.ID)), "bookmapping" // The name of the SqlResultSetMapping );result.forEach((Object[] entities) -> {JPAAuthor author = (JPAAuthor) entities[1];JPABook book = (JPABook) entities[0];System.out.println(author.firstName + " " + author.lastName + " wrote " + book.title); });

在這種情況下,結果仍然是Object[] ,但是這一次, Object[]并不表示具有單獨列的元組,而是表示由SqlResultSetMapping注釋聲明的實體。

這種方法很吸引人,當您需要映射查詢的任意結果但仍然需要托管實體時,可能會使用它。 如果您想了解更多信息,我們只能推薦Thorben Janssen關于這些高級JPA功能的有趣博客系列:

  • 結果集映射:基礎
  • 結果集映射:復雜映射
  • 結果集映射:構造函數結果映射
  • 結果集映射:休眠特定功能

結論

在ORM和SQL之間(特別是在Hibernate和jOOQ之間)進行選擇并不總是那么容易。

  • 當涉及到應用對象圖持久性時,即當您有很多復雜的CRUD(涉及復雜的鎖定和事務策略)時,ORM會大放異彩。
  • 當運行批處理SQL(用于讀取和寫入操作),運行分析和報告時,SQL表現出色。

當您“很幸運”時(例如,工作很簡單),您的應用程序僅位于安全柵的一側,您可以在ORM和SQL之間進行選擇。 當您“幸運”時(例如– ooooh,這是一個有趣的問題),您將不得不同時使用兩者。 ( 另請參閱Mike Hadlow關于該主題的有趣文章 )

這里的信息是:可以! 使用JPA的本機查詢API,您可以利用RDBMS的全部功能運行復雜的查詢,并且仍然可以將結果映射到JPA實體。 您不限于使用JPQL。

邊注

盡管過去我們一直在批評JPA的某些方面(有關詳細信息,請參閱JPA 2.1如何成為新的EJB 2.0 ),但我們的批評主要集中在JPA對注釋的濫用上。 當使用諸如jOOQ之類的類型安全API時,可以輕松地向編譯器提供所有必需的類型信息以構造結果。 我們堅信,將來的JPA版本將更積極地使用Java的類型系統,從而可以更流暢地集成SQ??L,JPQL和實體持久性。

翻譯自: https://www.javacodegeeks.com/2015/05/type-safe-queries-for-jpas-native-query-api.html

總結

以上是生活随笔為你收集整理的为JPA的本机查询API键入安全查询的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 亚洲最大成人在线视频 | 国产高潮自拍 | 国产精品无码一区二区无人区多人 | 国产精品一级二级 | 特大黑人巨交吊性xxxxhd | 亚洲欧洲视频在线观看 | 96视频在线 | 国产成人a亚洲精品 | 国产精品久久久久久亚洲调教 | 9191av| 亚洲a图| 天天综合精品 | 色久影院 | 美女扒开尿口让男人捅爽 | 精品国产一区二区在线观看 | 三上悠亚一区二区在线观看 | av网站网址| 久操热久操 | 黄网站在线观看 | 一本一道精品欧美中文字幕 | 少妇无套高潮一二三区 | 国产超碰人人 | 免费看一级一片 | 28一20岁女人一级 | mm131美女视频 | a级免费视频 | 免费成人av在线播放 | 久久精品婷婷 | 丝袜美女av | 欧美日韩国产综合网 | 中韩毛片| 欧美顶级metart裸体全部自慰 | 亚洲婷婷网 | 亚洲成人精品 | 久久久久久久国产精品视频 | 色爽爽爽 | 12av在线| 国产aⅴ精品一区二区果冻 台湾性生生活1 | 专干中国老太婆hd | 欧洲一区二区 | 国产凹凸一区二二区 | a天堂亚洲 | 懂色一区二区三区免费观看 | 午夜国产福利 | 精品视频久久久久久久 | 人妖黄色片 | 性一交一乱一色一视频麻豆 | 亚洲最大的网站 | sese国产| 日韩制服在线 | 欧美少妇在线 | 免费黄色网址在线观看 | 亚洲成人黄色av | 中国三级黄色 | 亚洲天堂一级 | 中文字幕免费高清在线观看 | 重口另类| 国产swag在线 | 麻豆视频一区二区三区 | 动漫美女靠逼 | 中文字幕在线日本 | 中文字幕va | 日韩中文字幕在线观看视频 | 久久国内免费视频 | 日韩区在线观看 | 男女叼嘿视频 | 日本黄色一区二区 | 99资源站| 2020国产精品视频 | 欧美熟妇精品一区二区 | 日本女人黄色 | 色男人天堂av | 精品人妻无码一区二区色欲产成人 | 狠狠操伊人 | 日本不卡一区二区三区视频 | 靠逼视频免费网站 | 亚洲国产精品久久久久婷婷老年 | 国产盗摄一区二区三区 | 波多野结衣一区二区三区免费视频 | 制服丝袜av在线播放 | 亚洲精品日日夜夜 | 日本一级片免费看 | 国产亚洲色婷婷久久99精品 | 91蜜桃臀久久一区二区 | 校园春色亚洲 | 麻豆黄色网 | 亚洲小说图片区 | www.com捏胸挤出奶 | 欧美激情精品久久久久久免费 | 干日本少妇 | 一本大道久久a久久综合婷婷 | 香蕉视频2020 | 日韩在线一区二区三区 | 日韩欧美视频免费观看 | 国产不卡av在线播放 | 亚洲第一在线播放 | 国产性70yerg老太 | 国产经典自拍 | 成人午夜精品一区二区 |