4

I have a table fruit with four columns id, name, color, shape.

entries in the table would be:

1, apple, red, round
2, banana, yellow, long
3, tomato, red, round
4, orange, orange, round

Now I made an entity class Fruit mapped to above table.

@Entity
@Table(name="fruit")
public class Fruit implements Serializable {

@Id
@Column(name="ID")
String id;

@Column(name="NAME")
String name;

@Column(name="COLOR")
String color;

@Column(name="SHAPE")
String shape;

//getters/setters goes here
}

In my DAO class, the code is:

String myQuery = "Select f.shape, f.name from Fruit f where f.shape = :shape";
Query query = this.em.createQuery(myQuery);
query.setParameter("shape", "round");

As obvious, running above query will return 3 rows.

I have a simple TO class FruitSearchTO

class FruitSearchTO
{
  String shape;
  String name;

  //getters/setters here
}

This TO complies with the rows returned by my query.

But in my DAO running something like:

List<FruitSearchTO> fruitList = new ArrayList<FruitSearchTO>();  
fruitList = query.getResultList();

is throwing exception java.lang.ClassCastException: [Ljava.lang.Object; incompatible with FruitSearchTO]

Where am I going wrong and what is the solution to this ?

Vicky
  • 16,679
  • 54
  • 139
  • 232

2 Answers2

6

The HQL you're using will return a List<Object[]>, each element of the List being an array with shape in position 0 and name in position 1.

You can make the HQL return a List<FruitSearchTO> using an AliasToBeanResultTransformer:

List fruitList = s.createQuery(
  "select f.shape as shape, f.name as name from Fruit f where f.shape = :shape;")
  .setParameter("shape", paramShape)
  .setResultTransformer( Transformers.aliasToBean(FruitSearchTO.class))
  .list();
FruitSearchTOdto = (FruitSearchTO) fruitList .get(0);

Alternatively, if FruitSearchTO has an appropriate constructor:, you can also achieve this with select new FruitSearchTO(f.shape, f.name).

Take a look at the Hibernate Reference chapter on HQL, particularly 15.6 The select clause chapter.

James DW
  • 1,815
  • 16
  • 21
Xavi López
  • 27,550
  • 11
  • 97
  • 161
  • Thanks Xavi.. let me try out this and get back to you!! – Vicky Oct 31 '11 at 10:14
  • Can you please paste your earlier answer. I am using older version of Hibernate and it does not have ResultTransformer method. – Vicky Oct 31 '11 at 10:17
  • got it!! thanks.. I could not verify the above answer due to version issues. however, the iterator version did work!! – Vicky Oct 31 '11 at 10:25
  • @JamesDW Thank you for your edit, it indeed seems that the DTO is not required to be included in the mappings. – Xavi López Oct 31 '11 at 12:38
4

In JPQL you have a NEW operator which allows you to create an instance of the object on-the-fly which doesn't have to be an entity itself (just like in your case - a DTO is not an Entity).

If you don't want to go with vendor-specific solution you might use the NEW operator or just iterate over resulting Object[] and create your DTO by yourself.

These might be a interesting materials for you: How can I avoid the creation of superfluous entities?, and a bit about the NEW operator.

Community
  • 1
  • 1
Piotr Nowicki
  • 17,914
  • 8
  • 63
  • 82