【问题标题】:DetachCriteria paginated query returns duplicate valuesDetachCriteria 分页查询返回重复值
【发布时间】:2015-01-21 05:45:26
【问题描述】:

我有一个分页的分离标准执行,它返回实体的行。实体类如下。

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

谁能帮我解决这个问题。

【问题讨论】:

    标签: java hibernate jpa pagination detachedcriteria


    【解决方案1】:

    我对 Criteria API 不是 100% 熟悉,但在不断变化 dc.setResultTransformer(CriteriaSpecification.ROOT_ENTITY); 至 dc.setResultTransformer(CriteriaSpecification.DISTINCT_ROOT_ENTITY);

    可能足以让您的结果得到浓缩。

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

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

    【讨论】:

      猜你喜欢
      • 2013-06-24
      • 1970-01-01
      • 1970-01-01
      • 2011-12-27
      • 2018-05-07
      • 1970-01-01
      • 2016-05-08
      • 1970-01-01
      • 2021-08-01
      相关资源
      最近更新 更多