11 Eylül 2018 Salı

JPA CriteriaBuilder Arayüzü - JPQL Yerine DSL Kullanırız

Giriş
Şu satırı dahil ederiz.
javax.persistence.criteria.CriteriaBuilder
javax.persistence.criteria.CriteriaQuery
Açıklaması şöyle
Criteria API introduces DSL (Domain Specific Language) to create queries. It allows us to write queries without SQL or JPQL, with Java and string references to entities' properties. As a result, we can build queries not from strings but Java objects. It adds some type-safety when we combine different predicates or add order by clause to the query. Still, a query can fail in runtime due to an entity property name typo.
JPA 2.0 Criteria API ile geliyor. Bu sınıf Predicate,Order gibi sınıflar için factory olarak düşünülebilir. Yaratılan bu nesneler CriteriaQuery nesnesine geçilir. Yani CriteriaQuery arayüzünün where cümlesini kurmak için kullanılır.

Bu sınıf yerine TypedQuery kullanmak çok daha kolay.

Kullanım
1. CriteriaBuilder.createQuery() ile CriteriaQuery nesnesi yarat
2.  CriteriaQuery.from () ile Root nesne yarat
3.  CriteriaQuery.select (root).where(cb.X());
şeklinde sorgu yap.

Örnek
Şöyle yaparız.
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<UserDTO> cq = cb.createQuery(UserDTO.class);
...
TypedQuery<UserDTO> query = em.createQuery(cq);

List<UserDTO> result = query.getResultList();
Örnek
Hibernate ile kullanıyorsak Session nesnesi EntityManager'den kalıttığı için  şöyle yaparız. select yapıyor bile olsak beginTransaction(), commit() yapılması gerekir.
public List findAllRoles() {
  try (Session session = getSessionFactory().openSession()) {
    session.beginTransaction();
    CriteriaBuilder builder = session.getCriteriaBuilder();
    CriteriaQuery<AuthRole> criteria = builder.createQuery(AuthRole.class);
    Root<AuthRole> root = criteria.from(AuthRole.class);
    criteria.select(root);
    List<AuthRole> roleList = session.createQuery(criteria).getResultList();
    session.getTransaction().commit();

    return roleList;
}
constructor
Şöyle yaparız.
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
and metodu
CriteriaQuery nesnesinin where() koşulunu doldurmak içindir.

Örnek
Şöyle yaparız
entityManager.getTransaction().begin();   

CriteriaBuilder cb = entityManager.getCriteriaBuilder();  
CriteriaQuery<User> cr = cb.createQuery(User.class);  
Root<User> root = cr.from(User.class);  

cr.select(root).where(  
        cb.and(  
                cb.like(root.get("email"), "%gmail.com"),  
                cb.equal(root.get("firstName"),
                cb.parameter(String.class, "name"))  
        )  
);  
cr.orderBy(cb.asc(root.get("lastName")));  

TypedQuery<User> query = entityManager.createQuery(cr);  
query.setParameter("name", "Alice");  

List<User> results = query.getResultList();  

entityManager.getTransaction().commit();  
entityManager.close();  

asc metodu
Şöyle yaparız.
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<UserDTO> cq = cb.createQuery(UserDTO.class);
Root<UserDTO> iRoot = cq.from(UserDTO.class);
... //set where clause on CriteriaBuilder
List<Order> orders = new ArrayList<Order>(2);
orders.add(cb.asc(iRoot.get("firstName")));
orders.add(cb.asc(iRoot.get("lastName")));

cq.orderBy(orders);
TypedQuery<UserDTO> query = em.createQuery(cq);

List<UserDTO> result = query.getResultList();
avg metodu
Root nesneden elde edilen bir Expression  alır.
Örnek
Şöyle yaparız.
Root<Student> teacher = query.from(Student.class);
query.multiselect(cb.avg(teacher.get("salary")),...);
createCreteriaUpdate metodu
Şöyle yaparız.
CriteriaBuilder builder = em.getCriteriaBuilder();
CriteriaUpdate<AdminUser> update = builder.createCriteriaUpdate(AdminUser.class);
Root<AdminUser> root = update.from(AdminUser.class);
update.set(root.get("enabled"), false);
update.set("userName", builder.concat(unameTimestamp, root.get("userName")));
update.where(builder.equal(root.get("projectID"), userID));
em.createQuery(update).executeUpdate();
createQuery metodu - resultClass
Örnek
Şöyle yaparız.
CriteriaQuery<Long> countQuery = criteriaBuilder.createQuery(Long.class);
Örnek
Şöyle yaparız.
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<UserDTO> cq = cb.createQuery(UserDTO.class);
equal metodu
Predicate yaratır. Örnek ver.

like metodu
Predicate yaratır. 
Örnek
Şöyle yaparız.
String columnName = ...;
String filter = ...;
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<UserDTO> cq = cb.createQuery(UserDTO.class);
Root<UserDTO> iRoot = cq.from(UserDTO.class);
Predicate predicate = cb.like(cb.lower(iRoot.<String>get(columnName)),
  "%" + filter.toLowerCase() + "%"));
Örnek
Şöyle yaparız
Predicate like = cb.like(cb.upper(entity.get(Entity_.column)),
"%" + inputstr.toUpperCase() + "%");
not metodu
Şöyle yaparız.
CriteriaBuilder cb = entityManager.getCriteriaBuilder();

// Select distinct aid from B
CriteriaQuery<B> bQuery = cb.createQuery(B.class);
Root<B> bRoot = bQuery.from(B.class);
bQuery.select(bRoot.get("a").get("id")).distinct(true);

// Select * from A where aid not in ()
CriteriaQuery<A> aQuery = cb.createQuery(A.class);
Root<A> aRoot = aQuery.from(A.class);
aQuery.select(aRoot).where(cb.not(aRoot.get("id").in(bQuery)));

TypedQuery<A> query = entityManager.createQuery(aQuery);
List<A> result = query.getResultList();

Hiç yorum yok:

Yorum Gönder