2015-01-21 5 views
0

엔티티의 행을 반환하는 페이지 매김 분리 기준 실행이 있습니다. 엔티티 클래스는 다음과 같습니다.DetachCriteria 페이지가 매겨진 쿼리는 중복 된 값을 반환합니다.

@Entity 
@Table(name="POS_T_HTL_ITEM_GROUP") 
public class HotelItemGroup extends Versioned { 

private static final long serialVersionUID = 1734461562543376947L; 

@Id 
@SequenceGenerator(name = "s_hotel_item_group", sequenceName = "POS_S_HTL_ITEM_GROUP") 
@GeneratedValue(strategy = GenerationType.AUTO, generator = "s_hotel_item_group") 
@Column(name = "HTL_ITEM_GROUP_ID") 
private Long id; 

@ManyToOne(fetch = FetchType.LAZY) 
@JoinColumn(name = "HOTEL_ID") 
private Hotel hotel; 

@ManyToOne(fetch = FetchType.LAZY) 
@JoinColumn(name = "ITM_GRP_ID") 
private ItemGroup itemGroup; 

@Transient 
private String action; 

/** 
* @return the id 
*/ 
public Long getId() { 
    return id; 
} 

/** 
* @param id the id to set 
*/ 
public void setId(Long id) { 
    this.id = id; 
} 

/** 
* @return the hotel 
*/ 
public Hotel getHotel() { 
    return hotel; 
} 

/** 
* @param hotel the hotel to set 
*/ 
public void setHotel(Hotel hotel) { 
    this.hotel = hotel; 
} 

/** 
* @return the itemGroup 
*/ 
public ItemGroup getItemGroup() { 
    return itemGroup; 
} 

/** 
* @param itemGroup the itemGroup to set 
*/ 
public void setItemGroup(ItemGroup itemGroup) { 
    this.itemGroup = itemGroup; 
} 

/** 
* @return the action 
*/ 
public String getAction() { 
    return action; 
} 

/** 
* @param action the action to set 
*/ 
public void setAction(String action) { 
    this.action = action; 
} 
} 

이는 분리 조건은 다음과 실행되는 dao 구현에있어서 구현된다.

@Override 
public Page<HotelItemGroup> findHotelItemGroupsByCriteria(HotelItemGroupDTO searchCriteria,Page<HotelItemGroup> pg) { 

    DetachedCriteria dc = DetachedCriteria.forClass(HotelItemGroup.class); 

    dc.createAlias("hotel", "htl"); 
    dc.createAlias("itemGroup", "itm"); 
    dc.createAlias("itm.majorGroup", "majGrp"); 
    dc.addOrder(Order.asc("majGrp.majorGroupName")); 


    if (searchCriteria.getHotelId() != null) { 
     dc.add(Restrictions.eq("htl.id", searchCriteria.getHotelId())); 
    } 

    if (searchCriteria.getMajorGroupId() != null) { 
     dc.add(Restrictions.eq("majGrp.id", searchCriteria.getMajorGroupId())); 
    } 

    if (searchCriteria.getItemGroupId() != null) { 
     dc.add(Restrictions.eq("itm.id", searchCriteria.getItemGroupId())); 
    } 

    return executeCriteria(dc, pg); 
} 

다음은 executeCriteria 메소드의 추상 메소드 구현입니다.

@SuppressWarnings("unchecked") 
@Transactional(readOnly = true) 
public <R extends Serializable> Page<R> executeCriteria(final DetachedCriteria dc, final Page<R> page) { 

    return (Page<R>) getJpaTemplate().execute(new JpaCallback() { 

     @Override 
     public Object doInJpa(EntityManager em) throws PersistenceException { 

      // Obtain Hibernate Session from EM 
      Session session = PersistenceUtil.getSession(em); 

      // Find Total & Update Page 
      dc.setProjection(Projections.rowCount()); 
      Criteria ctrTotal = dc.getExecutableCriteria(session); 
      page.setTotalRecords(((Number) ctrTotal.uniqueResult()).longValue()); 

      // Reset Criteria 
      dc.setProjection(null); 
      dc.setResultTransformer(CriteriaSpecification.ROOT_ENTITY); 

      // Perform Search & Update Page 
      Criteria ctrQuery = dc.getExecutableCriteria(session); 
      ctrQuery.setFirstResult(page.getStartPosition()); 
      if (page.getPageSize() > 0) { 
       ctrQuery.setMaxResults(page.getPageSize()); 
      } 
      page.setPageData(ctrQuery.list()); 

      return page; 
     } 
    }); 
} 

문제는 쿼리 당 15 개 개체의 결과 집합에 페이지 매김을합니다. 초기로드에서 첫 페이지를 요청하고 사용자가 두 번째 페이지를 요청하면 첫 번째 페이지에 있었던 중복 레코드가 들어있는 결과 집합을 반환합니다. 여기서 내가 뭘 잘못하고 있니? 페이지는 기본적으로 다음과 같은 속성으로 구성된 클래스입니다.

private long totalRecords = 0; 
private int startPosition = 0; 
private int pageSize = DEFAULT_PAGE_SIZE; 
private Collection<T> pageData = null; 

이 문제와 관련하여 도움을 받으실 수 있습니다.

답변

1

나는 Criteria API에 100 % 익숙하지 않지만, 변경하고 있습니다. dc.setResultTransformer (CriteriaSpecification.ROOT_ENTITY); ~ dc.setResultTransformer (CriteriaSpecification.DISTINCT_ROOT_ENTITY);

으로 결과가 압축 될 수 있습니다.

여기에서 문제는 별칭을 만드는 다중성과의 관계가 있다는 것입니다. 이것은 명시 적 조인이 실행 된 쿼리에서 수행 될 것으로 기대합니다.

위의 제안이 효과가 없다면 최상의 자체 디버깅 방법은 실행 된 쿼리의 로깅을 활성화하고 DB에 대해 수동으로 실행하는 것입니다. 원인이 빨리 분명 해져야합니다.