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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

编译时检查JPA查询

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

JPA提供了幾種查詢數據的方法。 可以根據各種標準(例如,所使用的語言(SQL與JPQL)或查詢是靜態的(編譯時間)還是動態的(執行時間))對此類替代方案進行分類。

靜態查詢是使用@Entity類定義本身中的注釋@NamedQuery ( javax.persistence.NamedQuery )和@NamedQueries ( javax.persistence.NamedQueries )定義的:

@NamedQuery(name="findAllCustomersWithName",query="SELECT c FROM Customer c WHERE c.name LIKE :custName")

另一方面, EntityManager提供的方法createQuery(…)createNativeQuery(…)分別采用JPQL或SQL查詢。

因此,可以在編譯或執行時定義查詢。

注意 :建議始終使用Query中的 setParameter(…)方法使用參數化查詢,以避免SQL注入漏洞。)

標準API

但是,JPA提供了另一種查詢對象的方法: Criteria API 。 確實,切換到JPA的動機之一是處理對象而不是SQL方言,不是嗎?

讓我們看一個示例代碼。

實體定義:

@Entity public class User {@Idprivate Integer userId;@Basic@Column(length=15, nullable=false)private String name;@Basic@Column(length=64, nullable=false)private String userDigestedPasswd;@Basic@Column(length=50, nullable=true)private String email;@Basic@Column(nullable=false)public Integer privilegeLevel;@Basic@Column(nullable=false)private Boolean active; }

讓我們查詢數據庫并檢查結果(使用JUnit):

public class UserTest {@Testpublic void testUserCriteria(){ EntityManagerFactory emf = null; EntityManager em = null; try {emf = Persistence.createEntityManagerFactory("criteria");em = emf.createEntityManager();final CriteriaBuilder cb = em.getCriteriaBuilder();final CriteriaQuery<User> q = cb.createQuery(User.class);final Root<User> users = q.from(User.class);final Predicate condition = cb.equal(users.get("privilegeLevel"), 5);q.select(users).where(condition).orderBy(cb.asc(users.get("userId")));em.getTransaction().begin();List<User> result = em.createQuery(q).getResultList();em.getTransaction().commit();assertNotNull(result);assertEquals(2, result.size());assertEquals(1, (int)result.get(0).getUserId());assertEquals("Pepe", result.get(0).getName());assertEquals(3, (int)result.get(1).getUserId());assertEquals("Dolores", result.get(1).getName());} catch (Exception e) {fail("Unexpected Exception " + e.getMessage()); } finally {if (em != null)em.close();if (emf != null)emf.close(); } } }

以下幾行顯示查詢的創建:

final CriteriaBuilder cb = em.getCriteriaBuilder();final CriteriaQuery<User> q = cb.createQuery(User.class);final Root<User> users = q.from(User.class);final Predicate condition = cb.equal(users.get("privilegeLevel);q.select(users).where(condition).orderBy(cb.asc(users.get("userId

首先,從EntityManager獲得CriteriaBuilder 。 然后,獲取一個CriteriaQuery實例,將該類設置為保存結果。 在我們的例子中, User.class

final CriteriaBuilder cb = em.getCriteriaBuilder(); final CriteriaQuery<User> q = cb.createQuery(User.class);

接下來,必須設置要對其運行查詢的實體:

final Root<User> users = q.from(User.class);

現在是時候設置查詢匹配條件了。 在示例代碼中,條件只是屬性privilegeLevel等于5:

final Predicate condition = cb.equal(users.get("privilegeLevel"), 5);

最后,構建查詢以在Root上添加條件。 也可以設置分組和排序選項(即,對userId設置升序排序):

q.select(users).where(condition).orderBy(cb.asc(users.get(“userId”)));

請查看CriteriaBuilder中的不同選項。 可以在CriteriaQuery中找到分組和排序選項。

使用元模型進行編譯時檢查

請注意,我們剛剛構建的查詢需要跟蹤對象屬性名稱。 例如,要構建查詢,請使用屬性privilegeLevel的名稱。 但是,如果稍后更改屬性名稱,則代碼將編譯并且僅在運行時失敗:

final CriteriaQuery<User> q = cb.createQuery(User.class);final Root<User> users = q.from(User.class);final Predicate condition = cb.equal(users.get("privilegeLevel"), 5);q.select(users).where(condition).orderBy(cb.asc(users.get("userId")));

那不好

幸運的是,使用元模型,我們將能夠構建編譯時檢查的查詢。 可以在The Java EE6 Tutorial中找到簡短的介紹。

使用元模型,代碼將引用對象的SingularAttribute,而不是使用包含對象屬性名稱的String。 因此,如果稍后更改對象屬性,則編譯器將為我們標記該屬性。

首先,必須創建對應的元模型類( EntityType )。 盡管可以通過多種方法實現,但對于openJPA實現,最簡單的方法可能是添加openJPA構建標志 : -Aopenjpa.metamodel = true

因此,我們創建了User_類,它是User的對應元模型類:

* Generated by OpenJPA MetaModel Generator Tool.?**/ package com.wordpress.tododev.criteria.entities; import javax.persistence.metamodel.SingularAttribute; @javax.persistence.metamodel.StaticMetamodel (value=com.wordpress.tododev.criteria.entities.User.class) @javax.annotation.Generated (value="org.apache.openjpa.persistence.meta.AnnotationProcessor6",date="Mon Mar 04 16:47:46 CET 2013") public class User_ {public static volatile SingularAttribute<User,Boolean> active;public static volatile SingularAttribute<User,String> email;public static volatile SingularAttribute<User,String> name;public static volatile SingularAttribute<User,Integer> privilegeLevel;public static volatile SingularAttribute<User,String> userDigestedPasswd;public static volatile SingularAttribute<User,Integer> userId; }

如果將此類添加到代碼庫中,則以后對User類的任何更改都不會引起注意。 而且,將自動生成的項目添加到代碼版本控制系統中不是一個好主意。

使用antmaven或類似工具,可以添加目標以創建元模型類。 在更改JPA實體后,應執行該目標。

也可以使用IDE。 例如,對于使用Eclipse的,只需要已經提到編譯標志添加屬性- > Java的反編譯>注解處理器和的lib(JAR)包含所選擇的JPA實現第廠路內注釋處理器的注釋處理器(可能導致自動模式下的編譯問題,前提是必須在使用它的代碼之前編譯元模型類)。

讓我們向套件添加另一個測試。 這個不會提供包含屬性名稱的String,而是使用metamodel類:

@Testpublic void testUserCriteriaMetaModel(){EntityManagerFactory emf = null;EntityManager em = null;try {emf = Persistence.createEntityManagerFactory("criteria");em = emf.createEntityManager();final CriteriaBuilder cb = em.getCriteriaBuilder();final CriteriaQuery<User> q = cb.createQuery(User.class);final Metamodel m = em.getMetamodel();final Root<User> user = q.from(m.entity(User.class));final Predicate condition = cb.equal(user.get(User_.privilegeLevel), 5);q.select(user).where(condition).orderBy(cb.asc(user.get(User_.userId)));em.getTransaction().begin();List<User> result = em.createQuery(q).getResultList();em.getTransaction().commit();assertNotNull(result);assertEquals(2, result.size());assertEquals(1, (int)result.get(0).getUserId());assertEquals("Pepe", result.get(0).getName());assertEquals(3, (int)result.get(1).getUserId());assertEquals("Dolores", result.get(1).getName()); } catch (Exception e) {fail("Unexpected Exception " + e.getMessage());} finally {if (em != null)em.close();if (emf != null)emf.close();}}

更相關的更改是user.get(User_.privilegeLevel)而不是users.get(“ privilegeLevel”)? user.get(User_.userId)而不是 ? users.get(“ userId”)。

  • 從GitHub下載源代碼。

翻譯自: https://www.javacodegeeks.com/2014/08/compile-time-checking-jpa-queries.html

總結

以上是生活随笔為你收集整理的编译时检查JPA查询的全部內容,希望文章能夠幫你解決所遇到的問題。

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