NOTE: There is a follow up here: <a href="http://unitedcoderscom.appspot.com/nico-heid/using-an-entitymanagerfactory-with-jpa-hibernate-and-wicket">Using an EntityManagerFactory with JPA, Hibernate and Wicket</a> which fixes some design flaws.</cite> If you followed the first article on hibernate: <a href="/nico-heid/java-persistence-hibernate-annotations">Java persistence with Hibernate and Annotations</a> you might be interested in how to create relationship between classes (or sql tables). Let's pretend we're writing a little blog software. We only need articles and comments. To keep it simple, one article can have many comments. Comments can have no comments. The database, once filled, should look like this: <blockquote> mysql> select * from BlogPost; +-------------+-----------------------------+---------------------+--------------------------+-----------+----------------+ | BLOGPOST_ID | content | date | path | published | title | +-------------+-----------------------------+---------------------+--------------------------+-----------+----------------+ | 1 | the content blows your mind | 2010-01-12 14:25:24 | /2010/01/a_monster_title | Y | a moster title | +-------------+-----------------------------+---------------------+--------------------------+-----------+----------------+ mysql> select * from Comment; +------------+---------------------+----------------------+ | COMMENT_ID | comment | blogPost_BLOGPOST_ID | +------------+---------------------+----------------------+ | 1 | and a lousy comment | 1 | +------------+---------------------+----------------------+ </blockquote> Simple enough. Because we're lazy and we've learned a bit since the last article, we let hibernate create the tables for us. Therefor add hibernate.hbm2ddl.auto=create-drop to your hibernate.properties file. Now we take a look at the two Java classes we need. First the BlogPost: <pre class="prettyprint"> import java.io.Serializable; import java.util.Date; import java.util.Set; import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.OneToMany; import javax.persistence.Table; import org.hibernate.annotations.Type; import com.unitedcoders.yawblog.persistence.dao.PersistenceUtil; @Entity @Table(name = "BlogPost") public class BlogPost extends PersistenceUtil implements Serializable { private Long id; private String title; private String content; private Boolean published; private Date date; private String path; private Set<Comment> comments; @Id @GeneratedValue(strategy=GenerationType.AUTO) @Column(name="BLOGPOST_ID") public Long getId() { return id; } public void setId(Long id) { this.id = id; } @Column public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } @Column public String getContent() { return content; } public void setContent(String content) { this.content = content; } @Column @Type(type="yes_no") public Boolean getPublished() { return published; } public void setPublished(Boolean published) { this.published = published; } @Column public Date getDate() { return date; } public void setDate(Date date) { this.date = date; } @Column public String getPath() { return path; } @OneToMany(fetch=FetchType.EAGER, cascade = CascadeType.ALL, mappedBy="blogPost") public Set<Comment> getComments() { return comments; } public void setComments(Set<Comment> comments) { this.comments = comments; } public void setPath(String path) { this.path = path; } }
And the comments:
import java.io.Serializable; import javax.persistence.AssociationOverride; import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; import javax.persistence.Table; @Entity @Table(name = "Comment") public class Comment extends Serializable { private Long id; private String comment; private BlogPost blogPost; @ManyToOne(fetch = FetchType.EAGER) public BlogPost getBlogPost() { return blogPost; } public void setBlogPost(BlogPost blogPost) { this.blogPost = blogPost; } @Id @GeneratedValue(strategy=GenerationType.AUTO) @Column(name="COMMENT_ID") public Long getId() { return id; } public void setId(Long id) { this.id = id; } @Column public String getComment() { return comment; } public void setComment(String comment) { this.comment = comment; } }
As you can see, the mapping magic is just a few annotation. In BlogPost you define the Comments as @OneToMany. Important is the mappedBy, this has to point to the member in the target class (Comment). In the Comment class itself you have to define the @ManyToOne relationship. Because the annotations are directly above the class names, hibernate knows which tables it has to map to each other.
And because we want to try it, here's some sample code for filling the DB
// s2 is the hibernate session, however you want to create it BlogPost bp = new BlogPost(); bp.setTitle("a moster title"); bp.setContent("the content blows your mind"); bp.setDate(new Date()); bp.setPath("/2010/01/a_monster_title"); bp.setPublished(true); Set set = new HashSet(); Comment c = new Comment(); c.setComment("and a lousy comment"); set.add(c); bp.setComments(set); c.setBlogPost(bp); s2.save(bp); s2.close();
That's it.
The full source and overhead can be found on github: http://github.com/nheid/yawblog
Check it out with: git clone git://github.com/nheid/yawblog.git v0.1.1

Nico Heid

Latest posts by Nico Heid (see all)
- Raspberry Pi Supply Switch, start and shut down your Pi like your PC - August 24, 2015
- Infinite House of Pancakes – code jam 2015 - July 13, 2015
- google code jam 2014 – magic trick - April 18, 2014