0

I have these two Entity java class which is referring the tables (jos_content & jos_article_section).

@Entity
@Table(name="jos_content", 
uniqueConstraints={@UniqueConstraint(columnNames="id")})
public class ContentEntity implements Serializable {
private int id; 
private Set<ArticleSectionEntity> josArticleSection;    
private String sefUrl;

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name="id", unique = true, nullable = false)
public int getId() {
    return id;
}   
public void setId(int id) {
    this.id = id;
}

@Column(name="sef_url")
public String getSefUrl() {
    return sefUrl;
}
public void setSefUrl(String sefUrl) {
    this.sefUrl = sefUrl;
}

@OneToMany(cascade = CascadeType.ALL)
@JoinColumn(name="article_id")
public Set<ArticleSectionEntity> getJosArticleSection() {
    return josArticleSection;
}
public void setJosArticleSection(Set<ArticleSectionEntity> josArticleSection) {
    this.josArticleSection = josArticleSection;
}
}


@Entity
@Table(name="jos_article_section", uniqueConstraints=    {@UniqueConstraint(columnNames="id")})
public class ArticleSectionEntity implements Serializable {
private int id; 
private int articleId;

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name="id", nullable=false, length=10)
public int getId() {
    return id;
}
public void setId(int id) {
    this.id = id;
}

@Column(name="article_id", nullable=false)
public int getArticleId() {
    return articleId;
}
}

I'm using Criteria interface with group by like this:

Criteria contentCriteria = session.createCriteria(ContentEntity.class, "content");
// Join two tables (jos_content, jos_article_section) on  jos_content.id =     jos_acticle_section.article_id
contentCriteria = contentCriteria.setFetchMode("josArticleSection", FetchMode.JOIN);
contentCriteria = contentCriteria.add(Restrictions.eq("content.id", storyId));
contentCriteria = contentCriteria.add(Restrictions.eq("content.state",1));          

//Start Group By Clause
PropertyProjection propProjection = Projections.groupProperty("content.id");
contentCriteria = contentCriteria.setProjection(propProjection);
//End Group By

When I running my application, i'm getting this output with error as:

contentCriteria >>>> CriteriaImpl(com.itgd.entity.ContentEntity:content[][content.id=374821, content.state=1]content.id)
14:24:39,649 INFO  [STDOUT] Hibernate: select this_.id as y0_ from jos_content this_  where this_.id=? and this_.state=? group by this_.id
14:24:39,659 ERROR [STDERR] java.lang.ClassCastException: java.lang.Integer cannot be cast to com.itgd.entity.ContentEntity

How do I have to resolve this error and is it possible to keep all the fields with group by, using Criteria interface? Please let know, if anyone guide me.

TOSHASHU123
  • 75
  • 1
  • 9
  • You would need result transformer like [here](http://stackoverflow.com/a/25616261/1679310) or just expect that the result will not be ContentEntity - but array of projected columns. Exactly that is said by exception: *"Result is int (content.id) ... not converted to ContentEntity* – Radim Köhler Sep 02 '14 at 10:29
  • Hi Radim Kohler,Can you please explain in brief? – TOSHASHU123 Sep 02 '14 at 10:55
  • Hi Radim Kohler, I have use this: PropertyProjection propProjection = Projections.groupProperty("content.id"); contentCriteria = contentCriteria.setProjection(propProjection); contentCriteria = contentCriteria.setResultTransformer(Transformers.aliasToBean(ContentEntity.clas‌​s)); and got all the values are null. – TOSHASHU123 Sep 02 '14 at 10:58

1 Answers1

1

We can use projections, to narrow the list of selected columns, but then we have to decide

  • will we work with a result represented as object[]
  • will we transform result into DTO (if possible to original entity)

If we would go with transformation, we have to help the transformer with column names. It is done with passing alias

PropertyProjection propProjection = Projections
   .groupProperty("content.id")
       .as("id") // the alias
   ;

contentCriteria
    .setProjection(propProjection)
    .setResultTransformer(Transformers.aliasToBean(ContentEntity.clas‌​‌​s));

List<ContentEntity> groupedEntities = contentCriteria.list();

then the result would be list of ContentEntity which would have filled only id. See:

The alias() and as() methods simply wrap a projection instance in another, aliased, instance of Projection.

or we can expect the result as object[]

Object[] results = contentCriteria.list();

EXTEND:

If we would like to get list of route entities we can convert the current query into DetachedCriteria

DetachedCriteria grouped = DetachedCriteria.forClass(ContentEntity.class, "grouped")
    // Filter the Subquery
    .add(...
    // SELECT The User Id  
   .setProjection(propProjection)

So, the above will return just IDs we like, and the main query will be filtered by them, while returning the full object (no need to transform)

Criteria query = session.createCriteria(ContentEntity.class, "content")
    .add( Subqueries.propertyIn("content.id", grouped) );

Check similar stuff here: Hibernate Criteria for "in subselect"

Community
  • 1
  • 1
Radim Köhler
  • 122,561
  • 47
  • 239
  • 335
  • what is the exception now? It is not ClassCastException as before right? – Radim Köhler Sep 02 '14 at 11:39
  • It's working but not sufficient because of I want to fetch all the fields which are defined into ContentEntity.java file. For above solution, I'm getting only one field value i.e. ID. Also, My query has changed, its displaying without joins. – TOSHASHU123 Sep 02 '14 at 11:40
  • Resulting query is: select this_.id as y0_ from jos_content this_ where this_.id=? and this_.state=? group by this_.id – TOSHASHU123 Sep 02 '14 at 11:40
  • 1
    Exactly. This is what you defined as criteria - return just the id of a group. If you want full entity - you have to use this criteria as detached one, and use them for subquery – Radim Köhler Sep 02 '14 at 11:41
  • this_.large_kicker_image as large9_0_1_, this_.large_kicker_image_alt_text as large10_0_1_, this_.fulltext as fulltext0_1_, this_.sef_url as sef12_0_1_, this_.metadesc as metadesc0_1_, this_.metakey as metakey0_1_, this_.kicker_image_caption as kicker15_0_1_, josarticle2_.article_id as article3_3_, josarticle2_.id as id3_, josarticle2_.id as id1_0_, josarticle2_.ordering as ordering1_0_, josarticle2_.article_id as article3_1_0_ from jos_content this_ left outer join jos_article_section josarticle2_ on this_.id=josarticle2_.article_id where this_.id=? and this_.state=? group by this_.id – TOSHASHU123 Sep 02 '14 at 11:41
  • Please, here you can see how to use subquery http://stackoverflow.com/a/20427782/1679310 – Radim Köhler Sep 02 '14 at 11:42
  • Can you help me out, how do I do that detached criteria. – TOSHASHU123 Sep 02 '14 at 11:42
  • My actual SQL query is SELECT c.id, c.sef_url, FROM jos_content c, jos_article_section a WHERE c.id = ? and a.article_id=c.id and c.state=1 group by c.id and expected required: select this_.id as id0_1_, this_.sef_url as sef12_0_1_ from jos_content this_ left outer join jos_article_section josarticle2_ on this_.id=josarticle2_.article_id where this_.id=? and this_.state=? How do I do that, please help? – TOSHASHU123 Sep 02 '14 at 11:53
  • Let me do check with your updated answer and will reply back to you. – TOSHASHU123 Sep 02 '14 at 11:56
  • 1
    Look, I can hardly help more. You should think about what the query should look like. If you need GROUP BY... then you need projections. But subquery also help. You have to create inner query and then filter by it the root query. Root query, can later contain some associations/joins... But I tried to answer your exception: int cannot be treated as ContentEntity.. good luck with Hibernate – Radim Köhler Sep 02 '14 at 11:58