2015-01-21 88 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);

可能足以让您的结果精简。

我希望这里的问题是您与您正在创建别名的多重性有关系。我期望这将导致在执行的查询中执行显式连接。

如果上面的建议没有效果,最好的自我调试方法是启用日志执行的查询并手动运行它们对数据库。原因应该很快变得明显。