views:

114

answers:

2

I have a spring-hibernate application which is failing to map an object properly: basically I have 2 domain objects, a Post and a User. The semantics are that every Post has 1 corresponding User.

The Post domain object looks roughly as follows:

class Post {

  private int pId;
  private String attribute;
  ...
  private User user;

  //getters and setters here

}

As you can see, Post contains a reference to User. When I load a Post object, I want to corresponding User object to be loaded (lazily - only when its needed).

My mapping looks as follows:

<class name="com...Post" table="post">
    <id name="pId" column="PostId" />
    <property name="attribute" column="Attribute" type="java.lang.String" />

    <one-to-one name="User" fetch="join"
        class="com...User"></one-to-one>
</class>

And of course I have a basic mapping for User set up.

As far as my table schema is concerned, I have a table called post with a foreign UserId which links to the user table.

I thought this setup should work, BUT when I load a page that forces the lazy loading of the User object, I notice the following Hiberate query being generated:

Select ... from post this_ left outer join user user2_ on this.PostId=user2_.UserId ...

Obviously this is wrong: it should be joining UserId from post with UserId from user, but instead its incorrectly joining PostId from post (its primary key) with UserId from user.

Any ideas? Thanks!

Update: Thanks to a couple of the posts below I now realize that I should have been using a many-to-one mapping instead of a one-to-one. I changed the mapping under post to the following:

<many-to-one name="User" class="com...User" column="uId"/>

But now I get a run-time error telling me that there is no attribute called uId. This makes sense since I do not have a uId column in my post domain object (I simply have a reference to a user object). Now I am really confused as to how I can get Hibernate to realize that it needs to map the foreign key from the post table to the user table. Should explicitly add a uId attribute to my post domain object to be a placeholder for the foreign key?

I hope I am making sense...

+1  A: 

Since a user has many posts, your association is in fact a "many-to-one", not a "one-to-one". It should work if you map it accordingly.

Edit: Yes, you can map the property Post.user on the Post with a "many-to-one", or the set User.posts in User with a "one-to-many", or both. Have you specified the name of your foreign key column?

Edit2: In Hibernate speak, a "column" in the database is mapped to a "property" in your Java-Class. That is, the column attribute contains the name of your foreign key column in the database, not the name of any property in your Java class. If I read your question right, you should use "UserId", not "uId".

Oh, and a fetch="join" can not be lazy, as it mandates that the user is fetched in the same query as the post.

meriton
Thanks, but is it correct to place this mapping in the "post" mapping? I tried this with similar incorrect results. I am not sure how to get it to join on UserId from the Post table since my domain objects don't have any notion of a foreign key, just a reference to a User object.
James
Thanks for your update, can you please elaborate what you mean by "have you specified the name of your foreign key column?", as I suspect that this could be my problem?
James
Thank you!!! I have wasted so much time on this...as you probably guessed I am new to hibernate...
James
A: 

That is the behaviour of a one-to-one mapping. They usually share a primary key. Hibernate is assuming that the primary key of post is teh same as the primary key of user. This page summarizes this behaviour.

I suspect that one user can actually have more than one posts though. That makes your mapping a one-to-many.

Vincent Ramdhanie
You are right about a user having more than 1 post. I am just confused as to where to place this mapping: under the mapping for Post or under the mapping for User?
James