4

I get a list from my query.list(). After that, I want to display the object inside this list but I got this error for this line for(Commerce[] c: this.newsList) {

java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Lcom.model.Commerce; com.action.CommerceAction.searchCommerces(CommerceAction.java:35)

Here is my code:

My business service

public List<Commerce[]> getCommercesBySearch(String categorie, String lieux) {
    Query query = hibUtil.getSession().createQuery("from Commerce c, Categorie ca,Lieux l "
            + "where c.categorie=ca.idCategorie and c.lieux=l.idLieux and"
            + " ca.libelle='" + categorie + "' and l.ville='" + lieux + "' ");
    List<Commerce[]> tuples = (List<Commerce[]>) query.list();
    return tuples;
}

My action class

private CommerceService service;
private Commerce commerce = new Commerce();
private List<Commerce[]> newsList;
public String searchCommerces() {
    String libelle = ServletActionContext.getRequest().getParameter("libelle");
    String ville = ServletActionContext.getRequest().getParameter("ville");
    this.newsList = service.getCommercesBySearch(libelle,ville);
    for(Commerce[] c: this.newsList){
        System.out.println(c[0].getNom());
    }
    if (this.newsList.size() > 0) {
        return SUCCESS;
    }
    addActionError("Il n'existe aucun commerce de cette catégorie dans cette ville");   
    return ERROR;
    }
Luiggi Mendoza
  • 81,685
  • 14
  • 140
  • 306
Nadk
  • 163
  • 2
  • 3
  • 9
  • Do you actually try to get a list of Commerce[]? I think you want to get a List only. Maybe you should check the type of the variable ""tuples" – Hoàng Long Mar 31 '15 at 15:29

3 Answers3

7

I am certain that this statement:

List<Commerce[]> tuples = (List<Commerce[]>) query.list();

produces an unchecked type conversion warning. Your code is polluting the heap by doing this unchecked type conversion. query.list() returns a raw List, which will contain Object[]. Here is the relevant Hibernate documentation:

Return the query results as a List. If the query contains multiple results per row, the results are returned in an instance of Object[].

Note that you cannot cast an array to an array of it's sub-type.

There are a couple of ways to fix this problem:

  1. Use List<Object[]> instead of List<Commerce[]>. You can then transform the result of the list() method into a more usable form, preferably within it's own method, before passing it on to the rest of your code. This is the preferable method if you need to select more than just the Commerce object.
  2. Add SELECT c to the beginning of your query, this will allow you to do a safe List<Commerce> cast.
Community
  • 1
  • 1
durron597
  • 30,764
  • 16
  • 92
  • 150
  • 1
    Great explanation of the problem. It will be great if you post how OP can solve this problem as well. – Luiggi Mendoza Mar 31 '15 at 15:28
  • @durron597 Thought you had a template or so for formatting. But good explanation actually. – Murat Karagöz Mar 31 '15 at 15:29
  • @MuratK. Thanks. I do have some practice at being the [Fastest Gun in the West](http://meta.stackexchange.com/questions/9731/fastest-gun-in-the-west-problem) – durron597 Mar 31 '15 at 15:32
  • And... your solution is not the best =\ – Luiggi Mendoza Mar 31 '15 at 15:33
  • @LuiggiMendoza there really aren't any good ways to solve this problem. It's stupid that the latest version of Hibernate is returning a raw type, for any reason ever. How would you do it? – durron597 Mar 31 '15 at 15:34
  • 1
    I would add `"SELECT c"` because OP wants/needs to obtain `Commerce` and there's this `"FROM Commerce c"` and do an (un)safe cast to `List` with no problems. And yes, Hibernate should offer method `List Query#list(Class)` to make sure the data obtained is from an exact class. – Luiggi Mendoza Mar 31 '15 at 15:36
  • 1
    thanks everybody for your help i added select c (the second solution) and that worked fine. – Nadk Mar 31 '15 at 15:52
3

Use select c before your from or you will have some trouble with the returned Object[]. If you don't use this, Hibernate will return a list of Object[] containing more than one object into this. For your problem it will be like:

  • Object[0] is an instance of Commerce
  • Object[1] is Categorie
  • Object[3] is Lieux
  • etc.

You will throw an ClassCastException if you try to cast Object[] into Commerce.

durron597
  • 30,764
  • 16
  • 92
  • 150
alias_boubou
  • 206
  • 4
  • 9
  • Hi, welcome to Stack Overflow! Please elaborate further on what the trouble with your returned `Object` is, and I would be happy to upvote this answer. – durron597 Mar 31 '15 at 15:43
  • Hi, thanks for the advice. I just wanted to add comment but i have not enough reputation. Hope it is more comprehensive now. – alias_boubou Mar 31 '15 at 17:06
  • I fixed your formatting some, and gave you an upvote. – durron597 Mar 31 '15 at 17:10
1

I think the problem lies here:

 Query query = hibUtil.getSession().createQuery("from Commerce c, Categorie ca,Lieux l "
        + "where c.categorie=ca.idCategorie and c.lieux=l.idLieux and"
        + " ca.libelle='" + categorie + "' and l.ville='" + lieux + "' ");
List<Commerce[]> tuples = (List<Commerce[]>) query.list();

That's not correct, considering your idea. I believe that your query should return a List<Commerce>, not List<Commerce[]>.

List<Commerce> tuples = (List<Commerce>) query.list();

To make that works, you need to add SELECT c in your query:

SELECT c from Commerce c, Categorie ca,Lieux l...

It will select a list of object Commerce. If you leave the query like originally, it will return a list of Object array (actually they are Commerce[], Categorie[], Lieux[]...). Not to mention you can't cast directly an array in Java, the objects aren't the same type anyway.

Hoàng Long
  • 10,221
  • 17
  • 71
  • 114
  • This answer is wrong. See my answer, which references the Hibernate documentation. It's not a `List`, it's a `List` – durron597 Mar 31 '15 at 15:36
  • @durron597: it's quite strange to me then. Maybe I'm out of touch, but could you please explain what will be in the List ? – Hoàng Long Mar 31 '15 at 15:39
  • 1
    If there are multiple objects created in the row, the array will contain all of these objects. So one will be a `Commerce`, the next `Object` will be something else, etc. – durron597 Mar 31 '15 at 15:42
  • Oh thanks for the info. I haven't read the question carefully I have updated my answer – Hoàng Long Mar 31 '15 at 15:45
  • This answer would be more useful to future visitors if you wrote it as if it had originally included the `SELECT c` bit, instead of saying "Edit: blah blah". StackOverflow is not a forum, it is a site for getting expert advice on questions; if people care about the history of an answer they can clicked on the edit link. If you fix it I will be happy to remove my downvote – durron597 Mar 31 '15 at 15:48
  • [Further reading about using the word EDIT:](http://meta.stackexchange.com/questions/127639/when-is-edit-update-appropriate-in-a-post) – durron597 Mar 31 '15 at 15:55