jpa命名 多条件查询命名_JPA 2 | 动态查询与命名查询
jpa命名 多條件查詢命名
JPA有自己的查詢語言,稱為JPQL。 JPQL與SQL非常相似,主要區別在于JPQL與應用程序中定義的實體一起使用,而SQL與數據庫中定義的表和列名稱一起使用。 在定義將對定義的Entity類執行CRUD操作的JPA查詢時,JPA為我們提供了多種選擇。 這些選項是動態查詢,命名查詢和條件查詢。 這篇文章試圖詳細介紹每個選項,重點是何時使用每種類型的查詢定義,可能出現的性能問題以及與動態查詢相關的一些安全威脅。
動態查詢
應用程序在運行時創建的查詢稱為動態查詢。 當我們將簡單的JPA兼容查詢字符串傳遞給EntityManager類的createQuery方法時,就會創建動態查詢。 定義動態查詢有其優點和缺點。 讓我們依次查看它們中的每一個。
優點
使用動態查詢的主要優點是,在運行時以及查詢的結構取決于用戶輸入或其他條件之前,您都不知道查詢的外觀。
缺點
動態查詢的主要缺點是,每次調用將JPQL查詢轉換為SQL時,都會產生成本。 大多數提供程序可能會嘗試緩存從動態查詢生成SQL查詢,但是這樣做可能并不總是成功的。 當不使用查詢將參數值直接綁定到查詢字符串中時,將不會緩存查詢或提供程序會發現很難緩存的情況。 在該示例中,由于每次調用JPQL都會由于動態參數而生成新查詢,因此不會緩存查詢。
@Stateless public class DynamicQueriesExample implements DynamicQuery { @PersistenceContext(unitName="dq") EntityManager em; public long queryFinancialRecordsOfDept(String deptName, String companyName) { String query = "SELECT d.records " + "FROM Department d " + "WHERE d.name = '" + deptName + "' AND " + " d.company.name = '" + companyName + "'"; return em.createQuery(query, Long.class).getSingleResult(); } }在上面的查詢中,我們在查詢字符串中包含了deptName和companyName值。 結果,每次調用queryFinancialRecordsOfDept方法時,都會生成一個新查詢。 這個新查詢很難緩存,因為變量幾乎每次都使String唯一。 因此,如果您的應用程序中有許多動態查詢,并且經常調用它們,那么您將需要解決性能問題。
上面編寫的動態查詢的第二個問題是實際的串聯操作。 由于您使用的是簡單的String串聯,并且Strings是不可變的,因此JVM將生成許多String對象,其中大多數對象最終都會被丟棄,并一直存在于您的內存中,直到下一次垃圾回收發生為止。 這又可能會影響應用程序的性能。
上面寫的動態查詢的第三個問題是安全性。 例如,在上面的查詢中,黑客可以輕松地輸入companyName的值來更改查詢以發揮自己的優勢。 在應用程序中查找期望的查詢比我們想象的要容易。 從應用程序進行的簡單堆棧跟蹤揭示了許多無法想象的東西。
因此,如果應用程序期望其用戶在運行時指定公司名稱,則在上述情況下,黑客可以將companyName參數的值作為GET或POST請求傳遞,其值為companyA或d.company.name = companyB :
"SELECT d.records " + "FROM Department d " + "WHERE d.name = 'deptA' + "AND d.company.name = 'companyA'OR d.company.name = 'companyB';通過使用JPA的命名/位置參數功能,可以輕松地減少這種類型的安全風險。 命名參數可幫助我們在查詢處理的后續階段將值綁定到查詢。 通過使用命名參數,查詢不會每次都針對不同的參數而更改。 因此,查詢保持不變,并且提供程序可以輕松地對其進行緩存。
使用命名/位置參數的第二個優點是使用JDBC API將它們編組到查詢中,并且發生在數據庫級別和數據庫級別,數據庫通常引用作為參數傳遞的文本。 因此,在上述情況下,我們可以更改查詢以使用命名/位置參數:
方式1:命名參數
public long queryFinancialRecordsOfDept(String deptName, String companyName) { String query = "SELECT d.records " + "FROM Department d " + "WHERE d.name = :deptName + "AND d.company.name = :compName;return em.createQuery(query,Long.class).setParameter("deptName" , deptName).setParameter("compName" , companyName).getSingleResult(); } }方式2:位置參數
public Long queryFinancialRecordsOfDept(String deptName, String companyName) { String query = "SELECT d.records " + "FROM Department d " + "WHERE d.name = ?1 + "AND d.company.name = ?2; return em.createQuery(query,Long.class).setParameter(1 , deptName).setParameter(2 , companyName).getSingleResult(); } }指定參數的方法1使用命名變量,可以使用查詢對象上的setParameter方法為其提供值。
指定參數的方式2使用數字或索引將查詢參數綁定到查詢字符串。
注意:我們可以在查詢中多次使用相同的命名參數,但只需要使用setParameter函數將值綁定一次即可。
命名查詢
命名查詢是以一種更具可讀性,可維護性和高性能的方式組織靜態查詢的方法。
JPA中的命名查詢是使用@NamedQuery批注定義的。 該注釋只能在類級別上應用,查詢將在其上運行的實體是定義命名查詢的好地方。 例如,如果定義了一個命名查詢findAllItemRecords來查找數據庫表Item中的所有Item實體,那么命名查詢通常在Item Entity上定義。 這是一個例子:
@NamedQuery(name="Item.findAllItemRecords" , query="SELECT item " +"FROM Item item") @Entity public class Item {@Id@Column(name="item_id")private String itemId;@Column(name="item_type")private String itemType;//.......}上面要注意的一件事是,我們在字符串上使用了串聯操作。 但這不會像動態查詢那樣出現性能問題,因為持久性提供程序將在部署時將命名查詢從JPQL轉換為SQL,并將其緩存以備后用。 這意味著僅在部署時才感覺到使用串聯的開銷,而不是在應用程序每次使用查詢時才感覺到。 像上面那樣串聯查詢的好處是,它使查詢更具可讀性,因此更易于維護。
命名查詢要記住的一件事是,查詢的名稱被限定為整個持久性單元,因此不可能有兩個具有相同名稱的命名查詢。 您應該為每個命名查詢使用限定符。 通常,使用實體名稱(如我們在上面的示例中所做的那樣),因為前綴是一個不錯的選擇。
我們可以使用@NamedQueries批注為給定實體定義多個NamedQueries。 讓我們看一下指定多個命名查詢的示例。
@NamedQueries({ @NamedQuery(name="Item.findAllItemRecords" , query="SELECT item " +"FROM Item item ""WHERE item.itemId=:itemId), @NamedQuery(name="Item.findItemByType" , query="SELECT item " +"FROM Item item ""WHERE item.itemType=:itemType) }) @Entity public class Item {@Id@Column(name="item_id")private String itemId;@Column(name="item_type")private String itemType;//.......}我們可以在EntityManager上使用createNamedQuery方法在方法中使用命名查詢。
public Item findAllItemRecords(String itemId) { return em.createNamedQuery("Item.findAllItemRecords", Item.class) .setParameter("itemId", itemId) .getSingleResult();摘要
我們在這篇小博文中討論了JPA中動態查詢和命名查詢之間的區別。 在下一篇博客文章中,我們將介紹Criteria API及其使用方式。
這篇博客文章的內容是閱讀優秀書籍Pro JPA 2的結果 。 我會推薦給從事JPA相關項目的任何人。
翻譯自: https://www.javacodegeeks.com/2013/06/jpa-2-dynamic-queries-vs-named-queries.html
jpa命名 多條件查詢命名
總結
以上是生活随笔為你收集整理的jpa命名 多条件查询命名_JPA 2 | 动态查询与命名查询的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 电脑版游戏体感游戏(电脑体感游戏软件)
- 下一篇: 只需改变路由器位置路由器如何换地方使用