EclipseLink – 23 – Criteria API – 01– Select
Merhaba Arkadaslar
Onceki bolumlerde JPQL konusunu inceledik , boylelikle JPQL kullanarak nasil sorgular yazabilecegimizi incelemis olduk. Aslina bakarsak JPQL , SQL ile son derece benzerlik gostermekteydi. Bir diger yaklasim olarak Query olusturmak icin kullanacagimiz yontem Criteria API yaklasimidir. Criteria API , JPA 2.0 versiyonuyla birlikte gelen bir ozelliktir.
Hello JPA Criteria API
Criteria API’yi en temel JPQL query uzerinden inceleyemeye baslayabiliriz. Tum Employee kayitlarini getirdigimiz JPQL sorgumuzu hatirlayalim ;
SELECT e from Employee31 e;
JPQL sorgumuzu Criteria API kullanarak yapmak istersek ;
@Override public List<Employee31> getAllEmployees() { CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder(); CriteriaQuery<Employee31> criteriaQuery = criteriaBuilder.createQuery(Employee31.class); Root<Employee31> empRoot = criteriaQuery.from(Employee31.class); criteriaQuery.select(empRoot); TypedQuery<Employee31> query = entityManager.createQuery(criteriaQuery); return query.getResultList(); }
- Oncelikle EntityManager objemizi kullanarak CriteriaBuilder objemizi olusturuyoruz.
CriteriaBuilder arabirimi , Criteria API icin ana kapidir (main gateway) , kalbi konumundadir.
CriteriaBuilder objesini EntityManager objesi uzerinden getCriteriaBuilder metodunu cagirarak elde ederiz (obtain)
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
- javax.persistence.criteria.CriteriaBuilder arabirimin sorgular/query icin 3 tane metot destekler.CriteriaQuery IS-A Query degildir! CriteriaQuery , AbstractQuery arabirimini kalitmaktadir , AbstractQuery de CommonAbstractCriteria arabirimini kalitmaktadir.
CriteriaQuery<Object> createQuery(); <T> CriteriaQuery<T> createQuery(Class<T> resultClass); CriteriaQuery<Tuple> createTupleQuery();
CriteriaQuery<Employee31> criteriaQuery = criteriaBuilder.createQuery(Employee31.class);
- Daha sonrasinda CriteriaQuery objesi uzerinden from metodunu kullaniyoruz. Geriye Root objesi donmektedir. root of query yani sorgunun cikis noktasi/kok dizini olarak isimlendirebilecegimiz Root objesini from metodunu cagirarak elde ederiz.Root arabirimi , From arabirimini kalitmaktadir. From arabirimi de Path arabirimini kalitmaktadir. Hiyerarsiyi inceleyecek olursak ;
public interface Root<X> extends From<X, X> { //} public interface From<Z, X> extends Path<X>, FetchParent<Z, X> { //} public interface Path<X> extends Expression<X> { // } public interface Expression<T> extends Selection<T> { // } public interface Selection<X> extends TupleElement<X> { // } public interface TupleElement<X> { // }
<X> Root<X> from(Class<X> entityClass);
- Daha sonrasinda CriteriaQuery instance’i uzerinden select metodunu cagiriyoruz ve arguman olarak javax.persistence.criteria.Root objesini veriyoruz.
- Son olarak onceki orneklerimizde oldugu gibi EntityManager uzerinden createQuery metodunu kullaniyoruz ve arguman olarak String JPQL ifadesi yerine CriteriaQuery objesini arguman olarak veriyoruz ve geriye getResultList metodunu kullanarak List sonucunu donuyoruz.
TypedQuery<Employee31> query = entityManager.createQuery(criteriaQuery); return query.getResultList();
CriteriaAPITest.java
System.out.println("getAllEmployees"); List<Employee31> allEmployees=jpqlService.getAllEmployees(); for(Employee31 emp : allEmployees){ System.out.println(emp); }
Ornegimizi calistirdigimizda ;
getAllEmployees Employee31 [id=1, name=John, surname=Robbins, salary=55000] Employee31 [id=2, name=Rob, surname=Freeman, salary=53000] Employee31 [id=3, name=Peter, surname=Gunton, salary=40000] Employee31 [id=4, name=Frank, surname= Sadler, salary=41000] Employee31 [id=5, name=Scott, surname=Brown, salary=60000] Employee31 [id=6, name=Rod , surname=Johnson , salary=62000] Employee31 [id=7, name=Sue, surname=Bellows, salary=54000] Employee31 [id=8, name=Stephanie, surname=Whitmore, salary=45000] Employee31 [id=9, name=Jennifer, surname=Libby, salary=52000] Employee31 [id=10, name=Sarah, surname=Proval, salary=59000] Employee31 [id=11, name=Marcus, surname=Ragno, salary=35000] Employee31 [id=12, name=Joe, surname=Hatlen, salary=36000] Employee31 [id=13, name=Jack, surname=Snooze, salary=43000]
Selecting Single Expressions
Eger sadece Employee’lere ait name alanini getirmek istiyorsak bu durumda JPQL ifademizi su sekilde yazabiliriz ;
Select DISTINCT e.name from Employee31 e
Criteria API kullandigimizda su sekilde yazabiliriz. Burada dikkat edecegimiz nokta empRoot.get metodunu name alanini getirmek icin kullaniyoruz.
Ikinci nokta olarak distinct(true) metodunu kullanarak sorgu icin distinct keywordunu eklemis oluruz.
@Override public List<String> getEmployeesName() { CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder(); CriteriaQuery<String> criteriaQuery = criteriaBuilder.createQuery(String.class); Root<Employee31> empRoot = criteriaQuery.from(Employee31.class); criteriaQuery.select(empRoot.get("name")).distinct(true); TypedQuery<String> query = entityManager.createQuery(criteriaQuery); return query.getResultList(); }
System.out.println("getEmployeesName"); List<String> allEmployeeNames= jpqlService.getEmployeesName(); for(String empName:allEmployeeNames){ System.out.println(empName); }
Ornegimizi calistirdigimizda;
getEmployeesName Peter Joe John Frank Sue Stephanie Marcus Jack Sarah Rob Scott Jennifer Rod
Selecting Multiple Expressions
Employee Entity icin salary ve name alanlarini getirmek istersek ;
Select e.name , e.salary , e.department.name FROM Employee e
JPQL ifadesi bir kac yontem kullanarak Criteria API icin uygun formata donusturebiliriz.
Burada onemli nokta ;
- CriteriaQuery icin javax.persistence.Tuple arabirimini kullaniyoruz. Tuple cok ogeli anlamina gelmektedir.
- Bir diger nokta olarak select metodu icerinde criteriaBuilder.tuple metodunu kullaniyoruz.
empRoot objesi uzerinden get metodunu kullanarak name ve salary ifadesini getiriyoruz. Dikkat edecek olursak deparment ifadesini getirdikten sonra tekrar get metodunu kullaniyoruz ve department’a ait name bilgisini getiriyoruz.
@Override public List<Tuple> getEmployeesDeptSalary() { CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder(); CriteriaQuery<Tuple> criteriaQuery = criteriaBuilder.createQuery(Tuple.class); Root<Employee31> empRoot = criteriaQuery.from(Employee31.class); criteriaQuery.select(criteriaBuilder.tuple(empRoot.get("name"), empRoot.get("salary"),empRoot.get("department").get("name"))); TypedQuery<Tuple> query = entityManager.createQuery(criteriaQuery); return query.getResultList(); }
Geriye List<Tuple> donmustuk. Tuple objesi uzerinden get metodunu kullanarak ilgili alanlara erisim sagliyoruz.
System.out.println("getEmployeesDeptSalary"); List<Tuple> allEmployeesDeptSalary= jpqlService.getEmployeesDeptSalary(); for(Tuple tp : allEmployeesDeptSalary){ System.out.println(tp.get(0) + " " + tp.get(1) +" "+ tp.get(2)); }
Ornegimizi calistirdigimizda ;
getEmployeesDeptSalary John 55000 QA Rob 53000 QA Peter 40000 QA Frank 41000 Engineering Scott 60000 Engineering Rod 62000 Engineering Sue 54000 Engineering Stephanie 45000 Engineering Jennifer 52000 QA Sarah 59000 Engineering Marcus 35000 Accounting
Bir baska yaklasim olarak createTupleQuery metodunu kullanabiliriz. Bu metod geriye CriteriaQuery<Tuple> objesi donmektedir. Dolayisiyla createQuery(Tuple.class) metodu ile ayni anlama gelecektir.
Bir diger nokta olarak select metodu icerisinde tuple metodunu cagirmak yerine CriteriaQuery de yer alan multiselect metodunu kullanabiliriz.
CompoundSelection<Tuple> tuple(Selection<?>... selections); CriteriaQuery<T> multiselect(Selection<?>... selections);
@Override public List<Tuple> getEmployeesDeptSalaryV2() { CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder(); CriteriaQuery<Tuple> criteriaQuery = criteriaBuilder.createTupleQuery(); Root<Employee31> empRoot = criteriaQuery.from(Employee31.class); criteriaQuery.multiselect(empRoot.get("name"), empRoot.get("salary"), empRoot.get("department").get("name")); TypedQuery<Tuple> query = entityManager.createQuery(criteriaQuery); return query.getResultList(); }
CriteriaApiTest.java
System.out.println("getEmployeesDeptSalaryV2"); List<Tuple> allEmployeesNameAndSalary = jpqlService.getEmployeesDeptSalaryV2(); for (Tuple tp : allEmployeesNameAndSalary) { System.out.println(tp.get(0) + " " + tp.get(1) + " " + tp.get(2)); }
JPQL de Constructor Expressions kullanmistik. Benzer sekilde bir yapiyi Criteria API icin uygulayalim ;
EmployeeDetails.java
public class EmployeeDetails { private String name; private int salary; private String departmentName; public EmployeeDetails(String name, int salary, String departmentName) { super(); this.name = name; this.salary = salary; this.departmentName = departmentName; } ... }
Dikkat edecek olursak createQuery(EmployeeDetails.class) olarak kullandik. Burada dilersek multiselect metodunu kullanabiliriz.
Ya da select metodu icerisinde construct metodunu kullanabiliriz. EmployeeDetails.class literalini arguman olarak verdikten sonra EmployeeDetails sinifinda tanimladigimiz yapilandiriciya uygun sekilde ifadeleri sirasiyla yaziyoruz.
@Override public List<EmployeeDetails> getEmployeeDetails() { CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder(); CriteriaQuery<EmployeeDetails> criteriaQuery = criteriaBuilder.createQuery(EmployeeDetails.class); Root<Employee31> empRoot = criteriaQuery.from(Employee31.class); // criteriaQuery.multiselect(empRoot.get("name"), empRoot.get("salary"), // empRoot.get("department").get("name")); criteriaQuery.select(criteriaBuilder.construct(EmployeeDetails.class, empRoot.get("name"), empRoot.get("salary"), empRoot.get("department").get("name"))); TypedQuery<EmployeeDetails> query = entityManager.createQuery(criteriaQuery); return query.getResultList(); }
CriteriaApiTest.java
System.out.println("getEmployeeDetails"); List<EmployeeDetails> allEmployeeDetails = jpqlService.getEmployeeDetails(); for (EmployeeDetails empDetails : allEmployeeDetails) { System.out.println(empDetails.getName() + " " + empDetails.getSalary() + " " + empDetails.getDepartmentName()); }
Bu uc ornegimiz de bize ayni sonucu verecektir;
getEmployeeDetails John 55000 QA Rob 53000 QA Peter 40000 QA Frank 41000 Engineering Scott 60000 Engineering Rod 62000 Engineering Sue 54000 Engineering Stephanie 45000 Engineering Jennifer 52000 QA Sarah 59000 Engineering Marcus 35000 Accounting
Kaynak kodlar : Injavawetrust.jpa
Yazimi burada sonlandiriyorum.
Herkese Bol Javali Gunler dilerim.
Be an oracle man , import java.*;
Levent Erguder
OCP, Java SE 6 Programmer
OCE, Java EE 6 Web Component Developer
Leave a Reply