2010-06-14 3 views
7

나는 타입 안전을 좋아한다. CriteriaQuery은 JPA 2.0을 가져온다. 그러나 보일러 플레이트 코드를 가져온다. 예를 들어 NamedEntity라는 엔티티가 있다고 가정 해 봅시다.이 엔티티에는 "name"이라는 id와 String 필드가 있습니다.이 엔트리에는 true로 설정된 고유 제한 조건이 있다고 가정합니다./복사를 피하기 각 쿼리 방법에 동일한 코드 라인을 붙여 넣기하기 위해 코드를 응축 할 수있는 방법이 있나요JPA 2.0에서 CriteriaQuery와 관련된 보일러 플레이트 코드의 양을 줄이는 방법이 있습니까?

public class NamedEntityManager 
{ 
    //inject using your framework 
    EntityManager entityManager; 

    //retrieve all existing entities of type NamedEntity from DB 
    public Iterable<NamedEntity> queryAll() 
    { 
     CriteriaBuilder builder = entityManager.getCriteriaBuilder(); 
     CriteriaQuery<NamedEntity> query = builder.createQuery(NamedEntity.class); 
     return entityManager.createQuery(query).getResultList(); 
    } 

    //retrieve a single entity of type NamedEntity from DB using specified name 
    public NamedEntity queryByName(String name) 
    { 
     CriteriaBuilder builder = entityManager.getCriteriaBuilder(); 
     CriteriaQuery<NamedEntity> query = builder.createQuery(NamedEntity.class); 
     Root<NamedEntity> root = query.from(NamedEntity.class); 
     query = query.where(root.<NamedEntity>get("name").in(name)); 

     //skipped the try/catch block for the sake of brevity 
     return entityManager.createQuery(query).getSingleResult(); 
    } 
} 

다음은 NamedEntityManager 같이 보일 수 있습니다 무엇입니까? 아마 어떻게 든 CriteriaQuery 객체를 재사용 할 수 있을까요?

+0

이 상황은 전략을 사용하여 쉽게 해결할 수 있습니다. 메소드가 say, WhereClauseBuilder 타입의 하나의 매개 변수 (인터페이스)를 취해야하는 private 메서드를 하나만 만들면 private 메서드는이 매개 변수에서 다양한 부분 (where 절)을 criteriaBuilder와 쿼리를 전달하는 메서드 호출을 통해 가져옵니다. 모든 public 메소드는 필수 절 where 절을 리턴하는 특정 WhereClauseBuilder를 사용하여 개인 메소드를 호출합니다. –

답변

0

코드의 양을 줄이는 방법이없는 것 같습니다. 타입 안전을 얻기 위해서는 무엇인가를 희생해야만했던 것 같습니다.

4

내가 그런 것을 찾고 있었는데, Querydsl (LGPL 라이센스)에서 JPA를 백엔드로 사용할 수 있습니다.

아직 읽는 중입니다.하지만 예제에서는 꽤 깨끗해 보입니다.

HQLQuery q = new HibernateQuery(session); 
QCat cat = new QCat("cat"); // query type 
List<Cat> cats = q.from(cat).where(cat.name.between("A", "B")).list(cat); 
+0

이 프레임 워크는 Criteria API와 관련이 없으며 자체적으로 존재하지만 확실히 살펴볼 가치가 있습니다. 이것을 언급 해 주셔서 고맙습니다. 기회가 생겼을 때 저는 그것을 탐구 할 것입니다! – Andrey

+0

Querydsl은 GPL 라이센스가 아니라 LGPL 라이센스입니다. –

4

JPA 2.1에서는 JPQL과 Criterias를 혼합 할 수 있습니다. 이러한 접근 방식을 사용하면 JPQL로 기본 쿼리를 정의한 다음 Criteria API를 사용하여 작은 부분을 동적으로 추가 할 수 있습니다.

API의 작은 부분 만 사용해야하기 때문에 API가 덜 복잡해집니다.

+1

JPQL과 Criteria Queries를 섞는 것이 합리적인지 잘 모르겠습니다. JPQL을 포함 시키면 Criteria API의 주요 아이디어 인 컴파일 타임 형 안전성을 제공합니다. – Andrey

+2

그것은 물론 상반 관계입니다. EL을 사용하는 것과 마찬가지로 일부 경우 주석을 사용하는 것과 같습니다. 유연성과 덜 자세한 코드를 위해 컴파일 타임의 안전을 고려해야합니다. 어쨌든 Linda (스펙 리드)가 JPA 2.1에서 이것을 심각하게 고려하고 있기 때문에 많은 사람들이 감각이 있다고 생각합니다. 순수 JPQL, Criteria와 혼합 된 JPQL, 그리고 Criterias 내에서조차도 유형 안전 및 유형 안전하지 않은 변형이 있습니다. 당신에게 효과가있는 것을 사용하십시오. –

0

방법은 시대에 뒤 떨어진,이 게시물에,하지만 당신은 내가이 중지 결국이

List<MyEntity> matchingEntities = new Jpa2Whatsoever(entityManager).select(MyEntity.class).where("id", id).where("due", new Date()).getResultList(); 

처럼 사용할 수 있습니다 나는 간단한 쿼리

public static class Jpa2Whatsoever { 

    private final EntityManager em; 

    public class Jpa2WhatsoeverProgress<T> { 

     private CriteriaQuery<T> cq; 
     private List<Predicate> predicates = new ArrayList<>(); 
     private Root<T> root; 

     public Jpa2WhatsoeverProgress(Class<T> type) { 
      this.cq = em.getCriteriaBuilder().createQuery(type); 
      this.root = cq.from(type); 

     } 

     public Jpa2WhatsoeverProgress<T> where(String attributeName, Object value) { 

      Predicate equal = em.getCriteriaBuilder().equal(root.get(attributeName), value); 

      predicates.add(equal); 
      return this; 
     } 

     public List<T> getResultList() { 
      Predicate[] predicatesArray = new Predicate[predicates.size()]; 
      TypedQuery<T> typedQuery = em.createQuery(cq.select(root).where(predicates.toArray(predicatesArray))); 

      List<T> resultList = typedQuery.getResultList(); 

      return Collections.unmodifiableList(resultList); 
     } 

    } 

    public Jpa2Whatsoever(EntityManager entityManager) { 
     this.em = entityManager; 
    } 

    public <T> Jpa2WhatsoeverProgress<T> select(Class<T> type) { 
     return new Jpa2WhatsoeverProgress<T>(type); 
    } 
} 

을 위해 내가 최근에 지어진 무엇을 추가 할. 나는 그런

  • 보다 큰 미만
  • 메타 모델 지원으로, 나는 단지 두 개의 질의를했고, 나는 그것으로 필요한 질의 특성을 얻을 수있는 DSL을 확장 할 것이다 것을보고 주로하기 때문에
  • QueryBuilder.currentDate() 및 서로 같은.

또한 실제로는 where을 호출하는 것이 좋지 않지만 실제로는 더 많은 SQLly and에 해당합니다. 어쨌든 누군가가 매우 간단한 쿼리 API에 관심이 있다면 아직 시도해 볼 가치가 있습니다.

BTW : 이름은 잊어 버리십시오.이 프로토 타입은 아무것도 아닙니다.

관련 문제