views:

502

answers:

1

I am not certain what I am doing wrong, but I have a class that has a class within it, so when I save the Skill class the user class also gets created, so when I do the join and I want to pull everything in at one time, I get a classcastexception.

This is how I am calling my query.

val retrieved_obj = em.createNamedQuery("findAllSkillsByUser").setParameter("username", user.username ).getResultList().asInstanceOf[java.util.List[Skill]]
assertEquals(1, retrieved_obj.size())
val retrieved = retrieved_obj.get(0).asInstanceOf[Skill]

This is my query: <query><![CDATA[from Skill a JOIN a.user u WHERE u.username=:username]]></query>

This is what hibernate is actually doing in my test:

Hibernate: insert into users (firstName, lastName, username, id) values (?, ?, ?, ?)
Hibernate: insert into skills (datestarted, name, position, rating, skill_user_fk, id) values (?, ?, ?, ?, ?, ?)
Hibernate: select skill0_.id as id64_0_, user1_.id as id63_1_, skill0_.datestarted as datestar2_64_0_, skill0_.name as name64_0_, skill0_.position as position64_0_, skill0_.rating as rating64_0_, skill0_.skill_user_fk as skill6_64_0_, user1_.firstName as firstName63_1_, user1_.lastName as lastName63_1_, user1_.username as username63_1_ from skills skill0_ inner join users user1_ on skill0_.skill_user_fk=user1_.id where user1_.username=?

I expect the problem is all the user1 parts in the select.

The Skill class just has some setters/getters, basically, so I removed most of the annotations but the foreign key one:

  var id : Int = _
  var name : String = ""
  var position : Int = _
  var dateStarted : Date = new Date()
  var rating : SkillRating.Value = SkillRating.unknown

  @OneToOne{val fetch = FetchType.EAGER, val cascade=Array(CascadeType.PERSIST, CascadeType.REMOVE)}
  @JoinColumn{val name = "skill_user_fk", val nullable = false}
  var user : User = _

This is the User class:

  var id : Int = _
  var firstName : String = ""
  var lastName : String = ""
  var username : String = ""

This is my error:

java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to jblack.resumeapp.lift.model.Skill

I would rather no just select the Skill attributes and then have to do another query for the user, as that will be less efficient as my classes get more complicated.

+2  A: 

You're selecting both Skill and User and getting back an object array containing both as elements.

You can either treat it as such or rewrite your query a bit:

select a from Skill a JOIN FETCH a.user u WHERE u.username=:username

to select only Skill but fetch and populate its User association.

ChssPly76
That was my concern. Is there no way to populate both classes with one query? Otherwise I will be making many queries to populate some of the more complicated data structures.
James Black
`JOIN FETCH` will populate both classes - perhaps I worded it badly in my answer. The actual SQL will be exactly the same as you see now, but Hibernate will create entities differently behind the scenes - populate `Skill` and `User`, set `User` on `Skill` and return `Skill`
ChssPly76
As far as more complicated structures go, you can do that (join fetch / left join fetch) for multi-level associations and even collections though you have to be careful with the latter for you may get duplicates.
ChssPly76
I had tried what you suggested, and I saw that it did indeed pull in the other classes. Thank you.
James Black