在本文的結尾,您將找到要下載的源代碼。
什么是標準? 當前是創建動態查詢的最佳解決方案。 想象一下一個頁面,該頁面允許用戶執行幾種類型的查詢; 所請求的查詢可以是按名稱,按年齡或二者兼有。 讓我們看一下如果連接一個String時查詢的外觀:
EntityManager em = emf.createEntityManager();
String hql = "select p from Person p where 1=1 ";if(parameters[0].equals("name")){hql += " and p.name = '" + values[0] + "'";
}if(parameters[1].equals("age")){hql += " and p.age = " + values[1];
}TypedQuery<Person> query = em.createQuery(hql, Person.class);System.out.println(query.getResultList());注意,在上面的代碼中進行了字符串連接; 請記住,這種做法是一種不良和危險的做法,因為它允許“ SQL Injection”黑客攻擊。 為了避免這種攻擊,我們應該使用帶有參數的查詢:
EntityManager em = emf.createEntityManager();
String hql = "select p from Person p where 1=1 ";if(parameters.contains("name")){hql += " and p.name = :name";
}if(parameters.contains("age")){hql += " and p.age = :age";
}TypedQuery<Person> query = em.createQuery(hql, Person.class);if(parameters.contains("name")){query.setParameter("name", values[0].toString());
}if(parameters.contains("age")){query.setParameter("age", Integer.valueOf(values[1].toString()));
}System.out.println(query.getResultList());注意,SQL注入問題已解決,但是現在代碼必須檢查參數以將其添加到查詢中,并在以后傳遞其值。 代碼需要兩個“參數搜索”來完成任務。
Java / Oracle開發人員在創建適用于這種情況的Criteria概念時有一個絕妙的主意。 在下面,使用本地JPA標準檢查代碼的外觀:
EntityManager em = emf.createEntityManager();
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Person> cq = cb.createQuery(Person.class);
Root<Person> root = cq.from(Person.class);
cq.select(root);if(parameters.contains("name")){Path<String> name = root.get("name");cq.where(cb.and(cb.equal(name, values[0])));
}if(parameters.contains("age")){Path<Integer> name = root.get("age");cq.where(cb.and(cb.equal(name, Integer.valueOf(values[1].toString()))));
}TypedQuery<Person> query = em.createQuery(cq);System.out.println(query.getResultList());有可能看到傳遞參數值更加容易。 無需連接字符串或檢查參數列表值以填充值。
不幸的是,Criteria API過于復雜和冗長。 如果您只想“從人物p中選擇p”,則需要創建以下條件:
EntityManager em = emf.createEntityManager();
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Person> cq = cb.createQuery(Person.class);
Root<Person> root = cq.from(Person.class);
cq.select(root);TypedQuery<Person> query = em.createQuery(cq);
System.out.println(query.getResultList());對許多代碼來說,如此簡單就可以從表中列出所有人。
為了避免所有這些冗長的細節,創建了名為EasyCriteria的開源項目。 如果開發人員使用EasyCriteria,則上面的查詢如下所示:
EntityManager em = emf.createEntityManager();
EasyCriteria<Person> easyCriteria = EasyCriteriaFactory.createQueryCriteria(em, Person.class);if(parameters.contains("name")){easyCriteria.whereEquals("name", values[0]);
}if(parameters.contains("age")){easyCriteria.whereEquals("age", values[1]);
}System.out.println(easyCriteria.getResultList());請注意,所有JPA詳細信息都已消失。 現在可以使用干凈的代碼,更輕松地創建動態查詢。 關于上面的代碼值得一談:
- 第2行:通過“工廠”創建EasyCriteria的實例。 該工廠的存在是為了對創建EasyCriteriaImp類型的對象所需的所有陡峭對象進行抽象。 在將來的版本中,將添加新類型的EasyCriteria,例如“ Tuple”。
- 第5和9行:傳遞參數更容易。 要將參數傳遞給比較值(“ name =:name”),只需使用equals方法,該方法將屬性名稱作為第一個參數。 第二個參數將是等于的值。
- 第12行:要運行查詢,就不必使用Query界面。 EasyCriteria本身承擔此責任。 可以通過EasyCriteria提取查詢結果。 有兩種方法可用于獲取查詢結果:EasyCriteria.getSingleResult(),EasyCriteria.getResultList()。
在EasyCriteria網頁上,可以找到幾個代碼示例以及可以使用的方法。 EasyCriteria的另一個優點是可以“鏈接”所有方法:
easyCriteria.whereEquals("name", values[0]).whereEquals("age", values[1]).getResultList();這是一個輕量級的庫,因為唯一的依賴關系是系統將需要的JPA。 注意:您的應用程序將需要啟動并運行JPA實現。
該庫是使用JUnit開發的,并已通過Hibernate,OpenJPA和EclipseLink進行了測試。 JUnit還使用Cobertura框架來檢查測試是否覆蓋了所有代碼行(或其中大部分),到目前為止,我們已覆蓋了100%。
EasyCriteria仍處于Beta版,但開發團隊已經計劃了一些版本和功能。
EasyCriteria的另一個優點是您的軟件代碼不再“耦合”到任何類型的JPA實現中。 今天,Hibernate具有良好的條件工具,但是您的代碼必須保持“附加”狀態。 使用EasyCriteria,您將能夠使用任何一種JPA實現。 這個解耦庫的證明是EasyCriteria已通過前面引用的3種實現進行了測試。
EasyCriteria具有以下方法:in,like,empty和其他。 開發人員將能夠使用Criteria進行連接(只是不帶參數的簡單連接),所有人都可以區分甚至排序。
在這里,您將找到EasyCriteria,可以下載并訪問其所有文檔。
單擊此處下載此帖子的源代碼。
我希望這篇文章/工具可以對您有所幫助。
參考: EasyCriteria –通過 uaiHebert博客的JCG合作伙伴 Hebert Coelho 使用JPA Criteria的簡便方法 。
翻譯自: https://www.javacodegeeks.com/2012/07/easycriteria-easy-way-to-use-jpa.html