2008-10-07 3 views
2

JPA에서 엔티티는 주석이 붙은 Plain Old Java Objects입니다. 그러나 저는 그들과 데이터베이스와 상호 작용할 수있는 좋은 방법을 찾지 못했습니다.Java 용 쿼리 "레이어"에 적합한 디자인 JPA

내 현재 응용 프로그램에서 내 기본 디자인은 항상 기본 키로 시퀀스 기반 ID를 갖기 때문에 대개 PK가 아닌 다른 속성으로 엔티티를 조회해야합니다.

  1. 난 정말이를 가진 싫어 :

    그리고 각 엔티티에 대한

    나는 모든

    /** 
    * @return A List of all MyEnts that have some property 
    * @param someProp some property 
    */ 
    public List<MyEnt> getAllMyEntsFromProp(final String someProp) { 
    
        try { 
         final Query query = entityManager.createQuery("select me from MyEnt me where me.someProp = :someProp"); 
         query.setParameter("someProp", someProp); 
         return query.getResultList(); 
        } catch(final NoResultException nre) { 
         log.warn("No MyEnts found"); 
        } 
        return new ArrayList<MyEnt>(); 
    } 
    

    그래서 몇 가지 변화에게 있습니다 쿼리 방법과

    @Stateless 
    public class MyEntApiBean implements MyEntApi { 
    
    
    @PersistenceContext(unitName = "xxx") @Inject EntityManager entityManager; 
    

    의 무 EJB를 EJB의 메소드는 엔티티 자체에 속하는 것으로 보이고 EJB 로컬 인터페이스는 nnoy 내 쓰레기.

  2. 각 메소드에서 "try, createQuery, getResultList, catch, log, return"(대부분 클로저가 없거나 Java에서 "statement"또는 somesuch의 결과)과 중복되는 것을 싫어합니다.

내 문제 중 하나 또는 둘 모두를 해결하는 엔티티와 데이터베이스와 상호 작용하는 더 좋은 방법에 대한 제안이있는 사람이 있습니까?

현재 제네릭과 리플렉션을 사용하여 일부 기본 메서드를 사용하여 중복을 줄이기위한 일반적인 쿼리 메서드 (문제 2)를 생각하고 있습니다 (나중에 검토를 위해 프로토 타입을 작성합니다).

감사합니다, 앤더스

답변

4

보십시오 심. Query Objects은 대부분의 작업을 처리하며 쉽게 확장 할 수 있습니다. 또는 비슷한 패턴을 항상 구현할 수 있습니다.

일반적으로 Seam은 JPA와 사용자가보기 및 비즈니스 계층 사이의 격차를 줄이기 위해 많은 유용한 정보를 제공합니다. Seam이 유용하기 위해서는 JSF를 사용할 필요가 없습니다.

1

많은 텍스트 검색을 수행하는 경우 Compass과 같은 색인 생성 프레임 워크를 고려해야합니다.
응용 프로그램에 적합한 지 여부는 잘 모르지만 그렇다면 코드 디자인과 성능이 향상 될 수 있습니다.

1

저는 실제로 Seam을 사용하고 있습니다. 그리고 Query 객체 제안은 최대 절전 모드 Criteria queries (예제로 쿼리) functionality을 찾도록 유도합니다. 그게 내가 찾고 있던 것과 아주 비슷해 보입니다.

어쩌면 기본 클래스에 있고 dash of generics ....일까요?

3

불필요하게 자세한 정보가 표시됩니다. 첫째, getResultList()는 반환 된 행이 없을 때 예외를 throw하지 않습니다 (적어도 Eclipse 또는 Toplink에서는 그렇지 않습니다. 다른 공급자가 전혀 다른 것을 상상할 수 없습니다). getSingleResult()는 getResultList()가 수행하지 않습니다. 또한, 그렇게 빌더 패턴을 사용할 수있는 또는 전혀없는 경우 빈 목록이있는 경우

@SuppressWarnings("unchecked") 
public List<MyEnt> getAllMyEntsFromProp(final String someProp) { 
    return entityManager.createQuery("select me from MyEnt me where me.someProp = :someProp") 
    .setParameter("someProp", someProp); 
    .getResultList(); 
} 

결과의 목록을 반환하기에 충분해야한다.두 가지가 참고 :

  1. @SuppressWarnings ("선택 해제")는 불필요하지만 일반적인 목록에 getResultList()에서 제네릭이 아닌 목록의 결과를 주조 달리 피할 수없는 경고를 제거한다;

  2. 아마도 MyEnt (일반적으로)에서 @NamedQuery로 createQuery() 호출을 대체 할 가치가 있습니다. 한 가지 방법은 배치 시간 유효성 검사와 다른 유용한 일을 가능하게하는 것입니다.

합리적으로 간결하고 완벽합니다.

1

Moin!

public class JPA { 
    @SuppressWarnings ("unchecked") 
    public static <T> T querySingle(
     EntityManager em, 
     Class<T> clazz, 
     String namedQuery, 
     Pair... params) 
    { 
    Query q = em.createNamedQuery(namedQuery); 
    for (Pair pair : params) { 
     q.setParameter(pair.key, pair.value);  
    } 
    List<T> result = q.getResultList(); 
    if (result.size() == 0) { 
     return null; 
    } 
    if (result.size() == 1) { 
     return result.get(0); 
    } 
    throw new 
     IllegalStateException(
     "To many result rows for query: " 
     + namedQuery 
     + " where " 
     + Arrays.toString(params)); 
    } 

    public static class Pair { 
    String key; 
    Object value; 

    public static Pair param (String key, Object value) { 
     return new Pair (key, value); 
    } 

    public Pair (String key, Object value) { 
     this.key = key; 
     this.value = value; 
    } 

    @Override 
    public String toString() { 
     return key + "=" + value; 
    } 
    } 
} 

그리고 사용 :

import static org.sepix.JPA.*; 
... 

String id = ... 
Customer customer = querySingle (em, Customer.class, 
         "Customer.findByID", Pair.param ("id", id)); 

나 :

String inquiryID = ... 
Boolean current = Boolean.TRUE; 
Inquiry inq = querySingle (em, Inquiry.class, 
         "Inquiry.findCurrent", 
         Pair.param ("inquiry", inquiryID), 
         Pair.param ("current", current)); 
다음

내 하나의 결과 버전 (내가 TopLink를 필수로 내 바탕 화면의 JPA 애플리케이션에서 사용)입니다

최고, 안부, 조쉬.

0

JPA를 다루는 데 도움이되는 Spring의 JpaDaoSupport를 사용하는 것을 선호합니다. 좋은 예가 여기에 http://github.com/rafalrusin/jpaqb/blob/master/src/test/java/jpaqb/CarDao.java입니다.

논리의 분리는 DAO 클래스 (데이터 액세스 개체)와 DTO (데이터 전송 개체)를 갖는 것입니다. DAO는 일반적으로 모든 필수 쿼리를 포함하고 DTO는 필드가있는 엔터티입니다.