I was trying to use Hibernate Annotations, which I think is great … I am happy with it… but I learnt some stuff which I know I will forget. So I am blogging it here, hopefully I will make sense and serve as a reminder for me when I need it. Maybe it might help someone else too… who knows…
Bidirectional One-To-Many
here I am trying to create a Bidirectional One-To-Many relationship between Question and Choice, a Question has many choices.
- Setup entities
@Entity
@Table (name = "QUESTION")
public class Question implements Serializable
{@Id
@GeneratedValue (strategy = GenerationType.AUTO)
@Column (name = “QUESTION_ID”)
private Long id;@Column (name = “TEXT”)
private String text;
……………
@Entity
@Table (name = "CHOICE")
public class Choice implements Serializable
{@Id
@GeneratedValue (strategy = GenerationType.AUTO)
@Column (name = “CHOICE_ID”)
private Long id;@Column (name = “TEXT”)
private String text;
…………… - Setup the ONE side on Question – I read ONE Question has MANY CHOICE(S).
Question
@OneToMany (mappedBy="question")
private Set choices = new HashSet();
mappedBy – means “I am not the owner side”, I am mapped by question from the other side of the relationship. It will also not create the database column which makes sense, I would expect a foreign key on the CHOICE table instead.
- Setup the Many side on Choice – I read on Choice.java MANY Choice has ONE Question
@ManyToOne
@JoinColumn (name="QUESTION_ID")
private Question question;
the @JoinColumn indicate the owning side of the relationship, it is responsible for updating the database column. It will create the QUESTION_ID column on the CHOICE table
- Reversing the Relationship so that the owning side is the Question instead
Question
@OneToMany
@JoinColumn (name = "QUESTION_ID")
private Set choices = new HashSet();
Choice
@ManyToOne
@JoinColumn (name="QUESTION_ID", updatable = false, insertable = false)
private Question question;
- Finally I need to use a List instead of Set – so I can preserve the order of the Choice(s).Question
@OneToMany (
cascade = {CascadeType.ALL},
fetch = FetchType.EAGER
)
@JoinColumn (name = "QUESTION_ID")
@org.hibernate.annotations.Cascade(
value = org.hibernate.annotations.CascadeType.DELETE_ORPHAN
)
@org.hibernate.annotations.IndexColumn(name = "CHOICE_POSITION")
private List choices = new ArrayList();
Choice
@ManyToOne
@JoinColumn (name="QUESTION_ID", nullable = false, updatable = false, insertable = false)
private Question question;
the @org.hibernate.annotations.IndexColumn defines the colum CHOICE_POSITION that will be used to maintain the order of the list. Some how reversing the ownership is the only way to get the IndexColumn to work
Taras
Dec 06, 2006 @ 00:28:11
Hi!
One question about @IndexColumn – I have to create field “CHOICE_POSITION” (as posted in your example) in db or not? If yes, then on what side of relationship? Thanks for response.
josian
Dec 07, 2006 @ 09:53:32
Yes, the column needs to be created but what I do is use the configuration.generateSchemaCreationScript(dialect);
which will automatically create the schema for me.
HTH
Wheazel
Jan 08, 2007 @ 23:53:46
Ty, really helped me out. Your example is way easier then the reference one.
Prashant Khanal
Feb 09, 2007 @ 13:37:40
Hey i am new to hibernate.
I am really confused about what are the advantages of bidirectional one-to-many over unidireational.i found this configuration hits the database with more queries than unidirectional. One more thing what is the use of IndexColumn.
josian
Feb 14, 2007 @ 14:08:11
I am not an expert either, but I suppose having a bidrectional mapping gives you flexibility and really depends on how you want to use your Pojos.
If you always access/use your “child” objects from the parent object, then there’s is no need to make them bi-directional
“IndexColumn” here is needed as I wish to maintain the order of the list. So that when I retrieve a “List” of “Choice” objects its order is preserve as the way I had put them in in the first place.
HTH
Nick
Mar 13, 2007 @ 14:04:10
If I use “IndexColumn” and then insert new elements (Choices) into the list after the Question has already been stored in the database, will all indexes be updated for the Question on the next merge()?
josian
Mar 16, 2007 @ 14:04:43
Yea I think so yes. I vaguely remember it as such. the indexColumn gets updated according to the order of the List. Give it a go 🙂
Marcelo
May 17, 2007 @ 21:48:11
Thank you for the example, it´s so simple and great!
Mike D.
Aug 10, 2007 @ 02:19:51
Great example, thanks!
Obi Wan
Aug 24, 2007 @ 06:20:18
How about if we want to join two tables foe OneToMany on different column names from both tables . What I mean that In one table I have column serverId and in other, I have SId and I need to join them
josian
Aug 24, 2007 @ 08:17:30
If you take a read at step 3, you can actually specify the column name in the “JoinColumn”.
So in your case I suppose it would be :
@ManyToOne
@JoinColumn (name=”SId”)
private Server server;
HTH
Jaap
Aug 30, 2007 @ 00:50:03
Thanks for this example, it helped me out a lot!
Fred
Aug 31, 2007 @ 00:30:20
Hi, I tried the IndexColumn in my DB (Oracle) and it didn´t work. The index column remains empty (no value at all), despites of the list´s size (I tried many list sizes).
Bruce LeSourd
Oct 18, 2007 @ 01:25:38
Why did you add
@org.hibernate.annotations.Cascade(
value = org.hibernate.annotations.CascadeType.DELETE_ORPHAN
)
in Step 5. This would seem to be redundant with or override
cascade = {CascadeType.ALL},
also on the Question.choices relationship.
Alan Jelden
Nov 30, 2007 @ 00:22:44
Great example! I’m not sure why it seems so difficult to find a straight forward example like this. I’ve got a question about step 4. It seems that after step 3, everything should be setup just fine. What is the point of reversing the relationship. Also, what does the term “owner” of the relationship mean to you?
SVK
Jan 01, 2008 @ 15:36:43
Hi,
When retrieving the list, would it return in some order? I mean using @IndexColumn, its always returning in the descending sort. Is there a way we could specify this order or is it some default?
josian
Jan 28, 2008 @ 18:43:57
I vaguely remember that DELETE_ORPHAN is a hibernate extension and not part of JPA….
Bruce LeSourd Says:
October 18, 2007 at 1:25 am e
Why did you add
@org.hibernate.annotations.Cascade(
value = org.hibernate.annotations.CascadeType.DELETE_ORPHAN
)
in Step 5. This would seem to be redundant with or override
cascade = {CascadeType.ALL},
also on the Question.choices relationship.
josian
Jan 28, 2008 @ 18:50:22
Regarding ordering the List using IndexColumn, I believe you can change the base from 0 to 1 like :
@org.hibernate.annotations.IndexColumn(name = “step_ordering”, base=1)
but I don’t think there’s a way to inverse it, if you want to keep it, it should just return you the list the way you put in… I also remember reading somewhere that you can specify retrieving in some order but not using @IndexColumn I think
HTH
SVK Says:
January 1, 2008 at 3:36 pm e
Hi,
When retrieving the list, would it return in some order? I mean using @IndexColumn, its always returning in the descending sort. Is there a way we could specify this order or is it some default?
i0n
Feb 23, 2008 @ 08:45:45
Hi. this help me very much.
But Work for me in a DB2/as400 in this form:
@Entity
public class tstEntity1 implements Serializable {
private Long id;
private List lista = new LinkedList();
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
public Long getId() {
return id;
}
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
@org.hibernate.annotations.Cascade(value = org.hibernate.annotations.CascadeType.DELETE_ORPHAN)
@org.hibernate.annotations.IndexColumn(name = “INDICE”)
public List getLista()
…
And the other class definition
@Entity
public class tstEntity2 implements Serializable {
private Long id;
private tstEntity1 padre;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
public Long getId() {…
@ManyToOne
@JoinColumn(name = “ID”, nullable = false, updatable = false, insertable = false)
public tstEntity1 getPadre() {…
i0n
Feb 23, 2008 @ 09:19:15
well may last post. work in a erratic way 😦
Marek
Apr 11, 2008 @ 20:33:25
Why not to use LinkedHashSet instead of LinkedList? In my particular case I need unique elemenst in collection. You mentioned that it’s all about holding order. So why not LinkedHashSet?
bascht
Apr 16, 2008 @ 20:08:07
Thank you.
nikhil
Jun 20, 2008 @ 09:15:20
Thanks dude!
Parmendra
Oct 14, 2008 @ 21:05:07
How to use @JoinColumn in @OneToMany case ?
Suppose in bidirectional association you defin @JoinColumn at @OneToMany side, is it still required to define @JoinColumn at @ManyToOne side.
jose
Mar 02, 2009 @ 22:28:31
Thank you! It makes perfect sense all your explanations! I’ve been going crazy untill I found you’re post. Do you know why is it not working the indexColumn if we use it on the other side?
jose
Mar 02, 2009 @ 23:46:00
I have one problem with this way of working. In my case I have and object A than contains a List of object B and B contains a List of C.
this solution means that if I want to insert and object C I have to get the whole Object A and then update the C list, it looks really ineficient. If I don’t want to get the whole object A I have to manage the index manually and I don’t think it’s the best choice.
can you help me out?
cheers
Sagappeno
Apr 22, 2009 @ 20:59:32
mm.. good one )
» Hibernate: Bidrektinales Mapping mit IndexColumn
May 12, 2009 @ 17:38:33
M.C.S.
Aug 27, 2009 @ 16:25:28
Everytime _the_ resource where I solve my (standard) problems. Great idea, great examples – thanks 🙂
William Antônio Siqueira
Sep 12, 2009 @ 23:12:04
Thanks, this help-me a lot /
Ricardo Espergue
Oct 24, 2009 @ 04:21:48
Awesome explanation, I have hard time searching for list mapping ordering.
Good Job!
SCK
Dec 04, 2009 @ 19:48:50
can you extend your example with Answer Entity
which will have oneToOne relation with Question
with question_id has shared primary key.
@Entity
@Table (name = “QUESTION”)
public class Question implements Serializable
{
@Id
@GeneratedValue (strategy = GenerationType.AUTO)
@Column (name = “QUESTION_ID”)
private Long id;
@Column (name = “TEXT”)
private String text;
……………
@OneToMany(cascade = CascadeType.ALL, mappedBy = “flHdr”)
@JoinColumn (name = “QUESTION_ID”)
private Set choices = new HashSet();
@OneToOne
private Answer answer;
}
@Entity
@Table (name = “CHOICE”)
public class Choice implements Serializable
{
@Id
@GeneratedValue (strategy = GenerationType.AUTO)
@Column (name = “CHOICE_ID”)
private Long id;
@Column (name = “TEXT”)
private String text;
……………
@ManyToOne
@JoinColumn (name=”QUESTION_ID”, updatable = false, insertable = false)
private Question question;
}
@Entity
@Table (name = “ANSWER”)
public class Answer implements Serializable
{
@Id
@GeneratedValue(generator = “foreign”)
@GenericGenerator(name = “foreign”, strategy = “foreign”,
parameters = {@Parameter(name = “property”, value = “question”)})
private Long id;
@Column (name = “answer”)
private String answer;
@OneToOne
@PrimaryKeyJoinColumn
private Question question;
…….
}
is the above code will do any changes needed because of i am getting exception.
@OneToOne or @ManyToOne on com.sample.Choice.question references an unknown entity: com.sample.Question
Asad
Dec 23, 2009 @ 00:33:12
That is good post..well i am having a problem and it is driving me nuts.
i have a scenario in which each product it link to some other product.
table = product
id (primary key),
link(pointing to id)
this link can and cannot be null.its kind of parent child realtion in one table..after searching and found nothing i thought may b my design is bad so i split the product table
table = product
id
table = pr_link
prod_id ()
link_id ()
both are foreign keys from product table. it is one to one relation and iam unable to fix it..please help thank you..
ms
May 13, 2010 @ 14:29:48
Hi,
I have 3 tables User, Role and Permission , User to role has one to many many mapping, and role to permission has one to many mapping.
My requirement is when i fetch user, i should get user, related roles and related permissions for the role.
ms
May 13, 2010 @ 14:30:45
Hi,
I have 3 tables User, Role and Permission , User to role has one to many many mapping, and role to permission has one to many mapping.
My requirement is when i fetch user, i should get user, related roles and related permissions for the role.
Fetch must be lazy. can any one help me to solve this
karthik
Sep 22, 2010 @ 13:58:37
This post was really helpful. Thanks…
Amol
Oct 04, 2010 @ 18:17:31
mappedBy – means “I am not the owner side” …
In your article what is actually a owner side?
Thanks for good article.
josian
Oct 04, 2010 @ 22:58:29
In this case where both Question and Choice are Entities, the owner side (Question) is the side I want to manage my Choices.
Check out page 266 Java Persistnece With Hibernate
Jan
Nov 25, 2010 @ 17:29:02
This worked for me only after I set JoinColumn to not-null on Question-side like this: @JoinColumn (name = “QUESTION_ID”, nullable=false).
Furthermore, for some reason I needed to specify column names as Java property names: “QUESTION_ID” to “question”.
imanzano
Aug 03, 2011 @ 18:13:12
Great example, thanks!
GK
Aug 12, 2011 @ 16:06:37
Thanks. This example is the easiest to understand I have come across so far.
Rohit Girme
Nov 11, 2011 @ 14:55:33
Very Good example. Really helpfull.
al.dexter (@al_dexter)
Jan 31, 2012 @ 21:19:11
Thanks! Good example!
Tom
Feb 07, 2012 @ 22:56:18
Please note that when combining INDEX_COLUMN and DELETE_ORPHAN cascade, you MUST NOT have a database constraint on the index column. Otherwise you will get Constraint Violation Errors, since hibernate inserts first and then resets the index.
zeeman
Mar 11, 2012 @ 17:13:28
Thanks for summarizing things up.
After a long time I had to use Hibernate again and this was a perfect refresh.
Thanks!
mandar
May 07, 2012 @ 14:02:54
Can any one tell me how i will create three tables with one to many mapping in hibernate annotation.
1.discussion(disc_ID,que_ID,ans_Id)
2.question(que_ID,question,date)
3.answer(ans_ID,answer,date)
random_guy
Jun 14, 2012 @ 02:40:05
Very helpful!
Gürcan Kavakçı
Nov 25, 2012 @ 09:44:49
Thank you, Very usefull tutorial.