2015-01-21 39 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個對象的結果集。在初始加載時,我請求第一頁,如果用戶請求第二頁,它將返回一組結果,其中包含第一頁中存在重複記錄的結果。我在這裏做錯了什麼? Page是基本由以下屬性組成的類。

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);

可能足以讓您的結果精簡。

我希望這裏的問題是您與您正在創建別名的多重性有關係。我期望這將導致在執行的查詢中執行顯式連接。

如果上面的建議沒有效果,最好的自我調試方法是啓用日誌執行的查詢並手動運行它們對數據庫。原因應該很快變得明顯。