-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 3 posts ] 
Author Message
 Post subject: Question on collections mapping
PostPosted: Mon Apr 14, 2008 4:31 pm 
Newbie

Joined: Mon Apr 14, 2008 4:11 pm
Posts: 1
Let's say we have a Student entity. Each student has a collection of grades. I would like to create Student instance, fill it with Grade instances, and save it:
Code:
//beginning transaction...
Student john = new Student();
Set<Grade> johnGrades = new HashSet<Grade>();
johnGrades.add(new Grade("English", 'A'));
johnGrades.add(new Grade("Chinese", 'B'));
john.setGrades(johnGrades);
//committing transaction here...

But Hibernate would not save these Grade instances with proper foreign keys to Student entity (they will be null). If I wanted to do this simple task, I would have to save Student entity first, then call something like
Code:
grade.setStudentId(studentId)
on each Grade instance, and finally save them.
My question is: is it possible to force Hibernate to assign Student foreign keys to Grade instances automatically? This automatism would be based on the fact, that Student entity contains a collection of Grade instances.


Top
 Profile  
 
 Post subject: Code?
PostPosted: Mon Apr 14, 2008 5:09 pm 
Newbie

Joined: Thu Mar 27, 2008 10:50 am
Posts: 13
Can you post the code for Student and Grade?
Assuming the association between Student and Grade is bidirectional, maybe you are not setting one side of the relation when grade(s) are added to a Student - as in aGrade.setStudent(aStudent)


Top
 Profile  
 
 Post subject: The object graph is your friend...
PostPosted: Mon Apr 14, 2008 5:14 pm 
Newbie

Joined: Mon Apr 14, 2008 1:33 pm
Posts: 3
I assume that Student and Grades are defined as two separate tables? I also assume that a student can have more than one grade. I also assume that the CourseName is part of the ID of your Grade record; as your example implies.

If so you can have hibernate use the object graph on the heap to determine the relationships between your objects; and set the appropriate foreign-keys on save.

You can do this by specifying a key-many-to-one relationship in your Grade mapping.

ex:

Code:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
   "-//Hibernate/Hibernate Mapping DTD//EN"
   "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" >
<hibernate-mapping package="myapp.dco">
     <class name="Grade" table="Grade">
          <composite-id name="key" class="GradePk">
               <meta attribute="use-in-equals">true</meta>
               <key-many-to-one column="StudentID" name="student" class="myapp.dco.Student" />
               <key-property column="CourseName" name="courseName" type="string" />
          </composite-id>
          <property column="LetterGrade" name="letterGrade" type="string" />
     </class>
</hibernate-mapping>


Next, modify your grade's key object (GradePK) to hold a reference to a Student.

ex

GradePk.java
Code:
public class GradePk{
   
   private Student student;
   private String courseName;
   ...
}


Grade.java
Code:
public class Grade{
   
   private GradePk key;
   private String letterGrade;
   ...
 
   public void setStudent( Student student ){
      key.setStudent( student );
   }


Finally, you'll want to add a mechanism to associate the objects by reference when adding Grades to your Student's grade set:

Code:
public class Student{

   private Set<Grade> gradeSet;
   ....
   public void addGrade( Grade grade ){

      // First associate the grade with the current user
      grade.setStudent( this );

      // Add the grade to the student's gradeSet
      gradeSet.add( grade );
   }
}


Make sure to map the grades collection on the Student.hbm.xml and set cascade="all-delete-orphan".

Since the relationship between Grade and Student is mapped by object reference:

Quote:
<key-many-to-one column="Student" name="student" class="myapp.dco.Student" /> )


and we set the object references up when we add grades:

Code:
   public void addGrade( Grade grade ){

      // First associate the grade with the current user
      grade.setStudent( this );
      gradeSet.add( grade );
   }


when hibernate saves the Student object and cascades the save operation to the set of grade objects Hibernate is smart enough to realize that the objects in the gradeSet are children of the student record and executes inserts in the appropriate order; IE: Insert Student; foreach grade insert grade. Better yet, it also assigns the parent student's ID into the studentID foreign-key column of the Grade object automatically.

You might want to check some of the documentation; as it's been a while since I've actually done this. Hopefully this is enough to get you started.

Cheers,
Aaron


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 3 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.