1

I'm new to Hibernate, and trying to use it in a Spring MVC application. I have a custom query like the following:

public List<MyResults> findEmployees() {
   String queryString = "select E.firstname, E.lastname, A.city, A.state
      from Employee E, Address A, where ...."; // whatever where clause
   SQLQuery query = this.sessionFactory.getCurrentSession().createSQLQuery(queryString);
   query.setString(...) // set query parameters
   return query.list();
}

This doesn't work. The query runs, but it returns a list of objects. How do I tell Hibernate to use my MyResults class?

class MyResults {
    private String firstName;
    // other fields in the search

    @Column(name = "FirstName")
    String getFirstName() {
        return firstName;
    }
    void setFirstName(String firstName) {
        this firstName = firstName;
    }

    // other getters & setters
}

I'm also not sure what annotations MyResults needs?

I've tried a couple things:

return (List<MyResults>)query.list();

though this cast doesn't do it.

I've tried using a ResultTransformer:

 query.setResultTransformer(new AliasToBeanResultTransformer(MyResults.class));  //done before the return

but that causes an

ClassClastException: MyResults cannot be cast to java.util.Map.

Can someone show me how to set this kind of query up correctly in Hibernate?

dur
  • 15,689
  • 25
  • 79
  • 125
Chris
  • 391
  • 2
  • 4
  • 15
  • Please, add the full `MyResults` class. It is unclear: `MyResults` is `DTO` or an entity. Does it has a plain structure or it has the nested objects. – v.ladynev May 24 '16 at 07:40
  • It's a DTO -- not an Entity. Just a plain structure. A few field variables with getters and setters. That's all. – Chris May 24 '16 at 16:54
  • 1
    So you don't need this `@Column(name = "FirstName")` – v.ladynev May 24 '16 at 16:56

3 Answers3

0

The cause of ClassClastException: MyResults cannot be cast to java.util.Map is that Hibernate converts aliases for column names to upper case — firstName becomes FIRSTNAME. And it is really need the setter setFIRSTNAME() in the DTO. Don't know, it is a bug or feature.

To solve this issue, please, see my answer to your other question:

mapping Hibernate query results to custom class?

Community
  • 1
  • 1
v.ladynev
  • 19,275
  • 8
  • 46
  • 67
0

One solution I found is using the NamedNativeQuery as suggested, but making MyResults an Entity. Like so:

@Entity
@NamedNativeQuery(name = "findMyResult",  query = "select E.firstname, E.lastname, A.city, A.state from Employee E, Address A, where ....", resultClass = MyResults.class)
class MyResults {
    private String firstName;
    // other fields in the search

    @Column(name = "FirstName")
    String getFirstName() {
        return firstName;
    }
    void setFirstName(String firstName) {
        this firstName = firstName;
    }
    // other getters & setters
}

Note however the Entity class is not annotated with @Table.

And then in my DAO class:

public List<MyResults> checkResults() {
    Query query = sessionFactory.getCurrentSession().getNamedQuery("findMyResult");
    query.setParameter("employeeID", "1234");
    return (List<MyResults>)query.list();
}

My question now is: why does this work?

dur
  • 15,689
  • 25
  • 79
  • 125
Chris
  • 391
  • 2
  • 4
  • 15
  • 1
    `@Table` doesn't need, if you have an `@Entity` annotation. I use `@Table` to specify a table name. It works, because of `@NamedNativeQuery` is a JPA way, a transformer is not used for that. – v.ladynev May 24 '16 at 21:02
  • 1
    @Chris: See [`NamedNativeQuery`](https://docs.oracle.com/javaee/6/api/javax/persistence/NamedNativeQuery.html): *The NamedNativeQuery annotation can be applied to an entity or mapped superclass.* so if you use `@Entity` it is working. But I think, this solution smells. – dur May 25 '16 at 08:12
  • @dur I have to agree the solution smells :) I don't like it myself. One of my coworkers just played around with things and got this to work. I guess my problem with all this is that I don't know enough of the basics of Hibernate to really know what's what. Feel like I'm throwing code at it without understanding the fundamentals. – Chris May 25 '16 at 14:42
-1

You can use named query instead.

@NamedNativeQuery(
name = "findMyResult",  query = "select E.firstname, E.lastname, A.city, A.state from Employee E, Address A, where ....",resultClass = MyResults.class
)
class MyResults {
    private String firstName;
    // other fields in the search

    @Column(name = "FirstName")
    String getFirstName() {
        return firstName;
    }
    void setFirstName(String firstName) {
        this firstName = firstName;
    }
    // other getters & setters
}

Named queries are global access and can call using getNameQuery

Query query = session.getNamedQuery("findMyResult")
.setString("employee_id", "7277");
Anish Barnwal
  • 152
  • 1
  • 6
  • I tried this solution, but now it doesn't find the named query :( In my DAO, I have: Query query = this.sessionFactory.getCurrentSession().getNamedQuery("findMyResult") query.setParameter("employee_id", "7277"); – Chris May 24 '16 at 16:58
  • Sorry, my comment wasn't finished: I tried this solution, but now it doesn't find the named query :( In my DAO: List checkResults(String employeeID) { Query query = this.sessionFactory.getCurrentSession().getNamedQuery("findMyResult") query.setParameter("employee_id", employeeID); List list = query.list(); return list; } but it's not finding "findMyResults", though the class should be being scanned in my config, since it's placed in with my other Entity classes that SessionFactory is scanning. Can a non-Entity class have a Named Query? – Chris May 24 '16 at 17:06
  • 1
    @Chris: See [NamedNativeQuery](https://docs.oracle.com/javaee/6/api/javax/persistence/NamedNativeQuery.html): *The NamedNativeQuery annotation can be applied to an entity or mapped superclass.*, so the answer is no. – dur May 24 '16 at 18:14