`
saram
  • 浏览: 45717 次
  • 性别: Icon_minigender_1
  • 来自: 郑州
社区版块
存档分类
最新评论

[转]hibernate使用DatachedCriteria分页关联查询以及去除重复

    博客分类:
  • Java
阅读更多

近来项目中用到DatachedCriteria做分页,涉及到关联查询产生的重复记录问题。

主要有三张表相关联,Commodity,OrderCommodityLink,Order 这里采用注解的方式进行对象与表的映射配置:

Commodity类:

Java代码  
@Entity    
@Table (name= "COMMODITY" )    
public   class  Commodity  implements  java.io.Serializable {    
        
     /**   
     * 商品ID   
     */    
     @Id   @GeneratedValue (strategy=GenerationType.IDENTITY)    
     @Column (name =  "COMMODITY_ID" , unique =  true , nullable =  false )    
     private  Integer commodityId;    
     /**   
     * 商品名称   
     */    
     @Column (name =  "COMMODITY_NAME" , length= 50 , nullable =  false )    
     private  String commodityName;    
   
     public  Integer getCommodityId() {    
         return   this .commodityId;    
    }    
   
     public   void  setCommodityId(Integer commodityId) {    
         this .commodityId = commodityId;    
    }    
     public  String getCommodityName() {    
         return   this .commodityName;    
    }    
   
     public   void  setCommodityName(String commodityName) {    
         this .commodityName = commodityName;    
    }    
}   
@Entity
@Table(name="COMMODITY")
public class Commodity implements java.io.Serializable {
 
 /**
  * 商品ID
  */
 @Id @GeneratedValue(strategy=GenerationType.IDENTITY)
 @Column(name = "COMMODITY_ID", unique = true, nullable = false)
 private Integer commodityId;
 /**
  * 商品名称
  */
 @Column(name = "COMMODITY_NAME", length=50, nullable = false)
 private String commodityName;

 public Integer getCommodityId() {
  return this.commodityId;
 }

 public void setCommodityId(Integer commodityId) {
  this.commodityId = commodityId;
 }
 public String getCommodityName() {
  return this.commodityName;
 }

 public void setCommodityName(String commodityName) {
  this.commodityName = commodityName;
 }
}OrderCommodityLink 类:

Java代码  
@Entity    
     @Table (name= "ORDER_COMMODITY_LINK" )    
     public   class  OrderCommodityLink  implements  java.io.Serializable {    
         @ManyToOne (fetch=FetchType.EAGER)    
         @JoinColumn (name= "ORDER_ID" , nullable= false )    
         private  Order order;    
            
         @ManyToOne (fetch=FetchType.EAGER)    
         @JoinColumn (name= "COMMODITY_ID" , nullable= false )    
         private  Commodity commodity;    
            
         public  Order getOrder() {    
             return  order;    
        }    
   
         public   void  setOrder(Order order) {    
             this .order = order;    
        }    
            
         public  Commodity getCommodity() {    
             return  commodity;        
        }        
            
         public   void  setCommodity(Commodity commodity) {    
             this .commodity = commodity;         
        }    
    }   
@Entity
 @Table(name="ORDER_COMMODITY_LINK")
 public class OrderCommodityLink implements java.io.Serializable {
  @ManyToOne(fetch=FetchType.EAGER)
  @JoinColumn(name="ORDER_ID", nullable=false)
  private Order order;
  
  @ManyToOne(fetch=FetchType.EAGER)
  @JoinColumn(name="COMMODITY_ID", nullable=false)
  private Commodity commodity;
  
  public Order getOrder() {
   return order;
  }

  public void setOrder(Order order) {
   this.order = order;
  }
  
  public Commodity getCommodity() {
   return commodity;  
  }  
  
  public void setCommodity(Commodity commodity) {
   this.commodity = commodity;  
  }
 }Order类:

Java代码  
@Entity    
@Table (name= "ORDERINFO" )    
public   class  Order  implements  java.io.Serializable {    
     /**   
     * 主键ID   
     */    
     @Id   @GeneratedValue (strategy=GenerationType.IDENTITY)    
     @Column (name= "ORDER_ID" , nullable= false )    
     private  Integer orderId;    
     /**   
     * 订单创建时间   
     */    
     @Column (name= "ORDER_CREATE_TIME" )    
     private  Date orderCreateTime;    
     @OneToMany (mappedBy= "order" ,cascade = {CascadeType.ALL}, fetch = FetchType.EAGER)    
     @JoinTable (name= "order_commodity_link" ,joinColumns={ @JoinColumn (name= "order_id" )},inverseJoinColumns= @JoinColumn (name= "order_id" ))    
     private  Set<OrderCommodityLink> orderCommoditys;    
     public  Integer getOrderId() {    
         return   this .orderId;    
    }    
   
     public   void  setOrderId(Integer orderId) {    
         this .orderId = orderId;    
    }    
     public  Date getOrderCreateTime() {    
         return   this .orderCreateTime;    
    }    
   
     public   void  setOrderCreateTime(Date orderCreateTime) {    
         this .orderCreateTime = orderCreateTime;    
    }    
     public  Set<OrderCommodityLink> getOrderCommoditys() {    
         return  orderCommoditys;    
    }    
   
     public   void  setOrderCommoditys(Set<OrderCommodityLink> orderCommoditys) {    
         this .orderCommoditys = orderCommoditys;    
    }    
}   
@Entity
@Table(name="ORDERINFO")
public class Order implements java.io.Serializable {
 /**
  * 主键ID
  */
 @Id @GeneratedValue(strategy=GenerationType.IDENTITY)
 @Column(name="ORDER_ID", nullable=false)
 private Integer orderId;
 /**
  * 订单创建时间
  */
 @Column(name="ORDER_CREATE_TIME")
 private Date orderCreateTime;
 @OneToMany(mappedBy="order",cascade = {CascadeType.ALL}, fetch = FetchType.EAGER)
 @JoinTable(name="order_commodity_link",joinColumns={@JoinColumn(name="order_id")},inverseJoinColumns=@JoinColumn(name="order_id"))
 private Set<OrderCommodityLink> orderCommoditys;
 public Integer getOrderId() {
  return this.orderId;
 }

 public void setOrderId(Integer orderId) {
  this.orderId = orderId;
 }
 public Date getOrderCreateTime() {
  return this.orderCreateTime;
 }

 public void setOrderCreateTime(Date orderCreateTime) {
  this.orderCreateTime = orderCreateTime;
 }
 public Set<OrderCommodityLink> getOrderCommoditys() {
  return orderCommoditys;
 }

 public void setOrderCommoditys(Set<OrderCommodityLink> orderCommoditys) {
  this.orderCommoditys = orderCommoditys;
 }
}根据订单中商品条目名称和订单创建时间进行查询每页显示5条订单,每条订单下嵌套显示其包含的商品条目。

service层封装了查询条件:

Java代码  
DetachedCriteria dc = DetachedCriteria.forClass(Order. class );    
dc.createAlias( "orderCommoditys" ,  "ocl" );    
                dc.createAlias( "ocl.commodity" ,  "com" );    
                dc.add(Restrictions.like( "com.commodityName" ,commodityName,MatchMode.ANYWHERE)); //关联查询;    
   
dc.add(Restrictions.ge( "orderCreateTime" ,startTime));    
dc.add(Restrictions.le( "orderCreateTime" ,endTime));    
   
List orderList = orderDAO.findPage(dc,page);                   
DetachedCriteria dc = DetachedCriteria.forClass(Order.class);
dc.createAlias("orderCommoditys", "ocl");
    dc.createAlias("ocl.commodity", "com");
    dc.add(Restrictions.like("com.commodityName",commodityName,MatchMode.ANYWHERE));//关联查询;

dc.add(Restrictions.ge("orderCreateTime",startTime));
dc.add(Restrictions.le("orderCreateTime",endTime));

List orderList = orderDAO.findPage(dc,page);    dao层:

Java代码  
public  List findPage( final  DetachedCriteria dc,  final  Page page) {    
        Criteria criteria = dc.getExecutableCriteria(getSession());    
        Integer totalCount = (Integer)criteria.setProjection(Projections.rowCount()).uniqueResult(); //记录总数    
        page.setRowCount(totalCount);    
        criteria.setProjection( null );    
            
        dc.setResultTransformer(CriteriaSpecification.ROOT_ENTITY);  //只返回根对象,不加此限制结果将返回数组,包含根对象与关联对象    
        criteria.setFirstResult(page.getFirst() -  1 );    
        criteria.setMaxResults(page.getPageSize());    
         return  criteria.list();    
    }   
public List findPage(final DetachedCriteria dc, final Page page) {
  Criteria criteria = dc.getExecutableCriteria(getSession());
  Integer totalCount = (Integer)criteria.setProjection(Projections.rowCount()).uniqueResult();//记录总数
  page.setRowCount(totalCount);
  criteria.setProjection(null);
  
  dc.setResultTransformer(CriteriaSpecification.ROOT_ENTITY); //只返回根对象,不加此限制结果将返回数组,包含根对象与关联对象
  criteria.setFirstResult(page.getFirst() - 1);
  criteria.setMaxResults(page.getPageSize());
  return criteria.list();
 } 初始查询结果中,页面上每个订单中有多少条商品,就会重复显示该订单多次,想到了去重,将

dc.setResultTransformer(CriteriaSpecification.ROOT_ENTITY);改为dc.setResultTransformer(CriteriaSpecification.DISTINCT_ROOT_ENTITY); 结果不重复了,但分页却有问题。本来是每页显示5条订单记录,现在第一页却显示了3条,3条订单中的商品条目记录加起来刚好是5条,原来分页对象不对,尽管去重了,但分页还是对去重前的结果集分页,CriteriaSpecification.DISTINCT_ROOT_ENTITY只是对查询后的结果进行过滤。

后来又发现建立关联时,order中的orderCommodityLink集合是级联的,也就是查order时,orderCommodityLink集合也会级联出来,所以造成的结果是left join出来的结果对于order来说肯定存在重复了。

所以在service代码中将DetachedCriteria dc = DetachedCriteria.forClass(Orderinfo.class) 改为:

DetachedCriteria dc = DetachedCriteria.forClass(Orderinfo.class).setFetchMode("orderCommoditys", FetchMode.SELECT);将关联的orderCommoditys集合对象采用查询方式抓取。

再次执行查询,每页正确显示5条订单记录,而不管订单中的商品条目数目了,只不过后台打印的sql语句多了5条

分享到:
评论

相关推荐

    Hibernate 多表连接分页查询示范项目

    总结,"Hibernate 多表连接分页查询示范项目"是一个实用的示例,它展示了如何在实际应用中利用 Hibernate Criteria API 实现复杂查询和分页,对于学习和掌握 Hibernate 的高级特性和数据库操作技巧非常有帮助。...

    hibernate 模糊查询 分页

    接下来,我们讨论分页查询。在处理大量数据时,一次性加载所有结果可能会导致性能问题。因此,通常会采用分页的方式来获取数据。在Hibernate中,我们可以使用`Criteria`或`Query`对象的`setFirstResult()`和`...

    STRUTS2+HIBERNATE详细的分页实现代码详细的分页实现代码

    提供的代码片段中展示了`KindEntityDao`接口的部分定义,其中包括了获取单个实体、保存、更新、删除以及分页查询等功能。 3. **DAO实现** `KindEntityDaoHibernate`类实现了`KindEntityDao`接口,并使用Hibernate...

    Hibernate分页查询小结

    Hibernate分页查询小结

    Struts和Hibernate分页及查询

    3. **编写DAO层**:定义数据访问对象(DAO)接口及其实现,这些方法通常包括增删改查以及分页查询。分页查询可能涉及到`setFirstResult()`和`setMaxResults()`这两个Hibernate的Query方法,它们分别设置查询的起始...

    hibernate分页Hibernate 分页的设计和编码

    使用Hibernate进行分页查询时,可以通过设置`FirstResult`和`MaxResults`来限制查询结果集的范围。 ```java Query queryObject = getSession().createQuery("FROM User"); queryObject.setFirstResult((currentPage...

    使用hibernate分页查询

    以下是如何使用Hibernate进行分页查询的详细说明: 1. **配置Hibernate分页**: 在Hibernate中,我们通常使用`Criteria`或`Query` API进行分页查询。`Criteria`提供了一种更面向对象的方式来执行SQL查询,而`Query...

    Hibernate分页查询原理解读

    ### Hibernate 分页查询原理详解 #### 一、引言 在大数据量处理场景下,分页查询是提高数据检索效率的重要手段之一。Hibernate作为Java领域内最常用的持久层框架之一,其内置的分页功能非常实用且高效。本文将深入...

    hibernate分页查询 数据库连接

    本篇将深入探讨Hibernate中的分页查询功能以及它如何处理数据库连接,帮助你更有效地管理大数据量的查询操作。 首先,我们来看一下什么是分页查询。在Web应用中,当用户需要浏览大量数据时,一次性加载所有数据不仅...

    ExtJs4.2+Mysql+Struts2+Hibernate3实现分页查询

    ExtJs4.2+Mysql+Struts2+Hibernate3实现分页查询 1.libs目录缺少hibernate核心jar包 2.libs目录缺少struts jar 3.WebRoot目录缺少ExtJs4.2核心类库 以上信息我都在项目里面注明了,因为这些内容的文件太大了,CSDN不...

    hibernate实现分页查询

    ### Hibernate 实现分页查询详解 #### 一、引言 在进行数据库操作时,为了提高用户体验和系统性能,分页查询是一项非常重要的技术。Hibernate作为Java领域内一个优秀的对象关系映射(ORM)框架,提供了强大的数据...

    Hibernate HQL查询 分页查询 模糊查询.docx

    2. **性能优化**: 对于大型数据集,应考虑使用`setFirstResult`和`setMaxResults`进行分页查询以提高效率。 3. **错误处理**: 在实际应用中,应添加适当的异常处理逻辑,确保程序的健壮性。 4. **事务管理**: 示例...

    hibernateHQL关联查询

    ### Hibernate HQL 关联查询详解 #### 一、引言 在进行数据库操作时,关联查询是必不可少的一部分,尤其在处理复杂的数据结构时更是如此。Hibernate作为一种流行的Java持久层框架,提供了强大的对象关系映射(ORM...

    spring-boot基于hibernate实现简单分页

    下面我们将详细介绍如何在Spring Boot项目中集成Hibernate,并创建一个分页查询的示例。 首先,我们需要在项目中添加Spring Boot的起步依赖(Starter)和Hibernate的相关依赖。在`pom.xml`或`build.gradle`文件中,...

    Hibernate连表查询 Hibernate连表查询

    如果查询结果包含多个字段,并且希望将这些字段封装成一个对象,则可以使用Hibernate的投影列表功能,或者手动创建一个新的类来存储查询结果。 ### 总结 本文主要介绍了Hibernate中的连表查询方法及其在实际开发中...

    基于hibernate_mysql分页通用源码

    【描述】中提到的"通用分页工具",通常会包含一个工具类或服务,用于处理数据的分页查询。开发者只需要传入必要的参数(如当前页、每页记录数等),就可以获取到分页结果,同时工具可能还会提供动态生成分页链接等...

    hibernate分页查询

    Hibernate,作为一个流行的Java对象关系映射(ORM)框架,为开发者提供了便捷的分页查询功能。让我们深入探讨Hibernate分页查询的相关知识点。 一、Hibernate分页原理 Hibernate分页查询基于SQL的LIMIT和OFFSET子句...

    Hibernate中分页查询的封装。

    总的来说,Hibernate的分页查询封装涉及到对Criteria或HQL的熟练运用,以及对数据库查询优化的理解。合理地封装分页查询能提高代码的可复用性和可维护性,同时为用户提供更好的性能体验。在项目开发中,可以根据具体...

    利用Struts2+Hibernate+maven进行分页查询

    在分页查询中,我们将使用Hibernate的Criteria或HQL(Hibernate Query Language)来构造查询语句,这些查询可以带有分页参数,如当前页码和每页记录数。Hibernate会自动处理SQL的生成和执行,极大地减少了手动编写...

    hibernate分页查询功能

    本示例中,我们看到如何利用Struts2、Spring和Hibernate这三个流行框架来实现分页查询功能。下面我们将详细讲解这个实现过程。 1. **UserDao接口**: UserDao接口定义了分页查询的方法,通过`getUser(int offset, ...

Global site tag (gtag.js) - Google Analytics