-->
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.  [ 4 posts ] 
Author Message
 Post subject: Composite Keys - Best way to do this in Hibernate?
PostPosted: Thu Oct 30, 2008 1:20 pm 
Newbie

Joined: Thu Jul 24, 2008 10:13 am
Posts: 17
Hi all! My problems with Hibernate and composite keys continue, and now I have to solve a situation a bit difficult and I can't do it in Hibernate. Now I'll explain the situation (it's related with researchers and education):


- Suppose we have an entity Gender ( which represents the gender of a person)

- The researcher has a "link" with it's researching group (it doen't matter the meaning of that), and also, each link can have some "figures" (the figure of the researcher into the researching group). This two elements are entities and persist into database.

- For each of this elements, an internationalization is required, so we have some attributes to save its name in the corresponding language (in this case: galician, spanish and english)

- Due to split the name of this elements according to the gender (something like "king-queen"), we also need the gender into the primary key of each entity to manage this situation.

So, the entities would be like this:

* Link (Composite Primary key: link_id & gender)

- link_id
- gender
- nameES
- nameEN
- nameGL


* Figure (Composite Primary key: figure_id & gender)

- figure_id
- gender
- nameES
- nameEN
- nameGL


This works in my application (I'm using the approach of making a "primary key object" with the involved properties). But now I need to connect them with a many-to-many association (with one attribute in it):

- A link can have zero or more figures
- A figure can have one or more link


So, thinking it in a classic SQL way, the primary key of the relationship would be:

(link_id, link_gender, figure_id, figure_gender)

-- notice that the gender must mach and have the same value, so in a simplified way: --

(link_id, gender, figure_id)


According to this information, ¿how can I declare and annotate the relation entity to make it work linking these elements ?


P.D. : The link entity will have a collection of figures to associate between them, so I need to access figures form his link through the association entity.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Oct 30, 2008 10:17 pm 
Beginner
Beginner

Joined: Fri Sep 12, 2008 10:55 am
Posts: 33
Assuming that you have a class Link/LinkId and a class Figure/FigureId...probably something like:

Code:
@Embeddable
public class FigureId implements java.io.Serializable
{
   private Integer figureId;
   private String gender;

        @Column(name="figure_id"...)
        public Integer getFigureId()
        {
             return figure_id;
         }
...
}

public class LinkId implements java.io.Serializable
{
   private Integer linkId;
   private String gender;

        @Column(name = "link_id")
   public Integer getLinkId()
       {
      return this.linkId;
   }
...
}

public class Figure  implements java.io.Serializable
{
     private FigureId id;
     private String nameEs;
     private String nameEn;
     private String nameGl;

     private Link link;

     @EmbeddedId
     public FigureId getId() { return this.id }

.... other getters/setters w/@Column defs

      @ManyToMany
   @JoinTable(name = "link")
   public Set<Link> getLinks()
       {
      return links;
   }
...
}

public class Link  implements java.io.Serializable
{
....
     private Set<Figure> figures;

....

     @ManyToMany(mappedBy="links")
   public Set<Figure> getFigures()
      {
      return figures;
   }
...
}


Top
 Profile  
 
 Post subject:
PostPosted: Fri Oct 31, 2008 6:15 am 
Newbie

Joined: Thu Jul 24, 2008 10:13 am
Posts: 17
Thanks for your quick reply sdparsons. Good answer, but it has one problem:

Gender attribute is an entity that persist into database, so the primary key of any of the explained entities is composed by Gender + Integer (this is the real problem: a composite key with an entity as part of itself).


¿Perhaps an approach like this could work? (this doesn't work, but maybe I'm doing something wrong):

* In Link :

Code:
   @ManyToOne
   @JoinTable(name = "link_figures",
         joinColumns = { @JoinColumn(name = "link_fig_fig"),
                     @JoinColumn(name="link_fig_gend") },
         inverseJoinColumns={@JoinColumn(name="link_fig_link"),
                        @JoinColumn(name="link_fig_gend") } )
   private List<Figure> linkFigures;



The exact error:

Code:
A Foreign key refering es.udc.lbd.portal.model.researcher.tests.ResearcherLink from es.udc.lbd.portal.model.researcher.tests.ResearcherLink has the wrong number of column. should be 1


Maybe this problem is due to using an @EmbeddedId in wich the join columns are two, but I don't really know...

Any ideas?



P.D. : The SQL code of the "join table" is this:

Code:
DROP TABLE IF EXISTS link_figures CASCADE;
CREATE TABLE link_figures
(
   link_fig_fig   INT,
   link_fig_link   INT,
   link_fig_gend   INT,
   CONSTRAINT PK_LINK_FIG PRIMARY KEY(link_fig_fig,link_fig_link, link_fig_gend),
   CONSTRAINT FK_LINK_FIG_FIG FOREIGN KEY(link_fig_fig, link_fig_gend)
      REFERENCES researcher_figure(rese_fig_id, rese_fig_gend),
   CONSTRAINT FK_LINK_FIG_LINK FOREIGN KEY(link_fig_link, link_fig_gend)
      REFERENCES researcher_link(rese_link_id, rese_link_gend),
   CONSTRAINT FK_LINK_FIG_GEND FOREIGN KEY(link_fig_gend)
      REFERENCES gender(gend_id)
);


Top
 Profile  
 
 Post subject:
PostPosted: Fri Oct 31, 2008 7:58 am 
Newbie

Joined: Thu Jul 24, 2008 10:13 am
Posts: 17
Finally solved!

I was trying to use the gender column once (because its data is repeated), but hibernate needs each column to avoid "repeated mappings". Hope this help other people in similar cases:


SQL

Code:
DROP TABLE IF EXISTS link_figures CASCADE;
CREATE TABLE link_figures
(
   link_fig_fig      INT,
   link_fig_link      INT,
   link_fig_gend_fig   INT,
   link_fig_gend_link   INT,
   CONSTRAINT PK_LINK_FIG PRIMARY KEY(link_fig_fig,link_fig_link, link_fig_gend_fig, link_fig_gend_link),
   CONSTRAINT FK_LINK_FIG_FIG FOREIGN KEY(link_fig_fig, link_fig_gend_fig)
      REFERENCES researcher_figure(rese_fig_id, rese_fig_gend),
   CONSTRAINT FK_LINK_FIG_LINK FOREIGN KEY(link_fig_link, link_fig_gend_link)
      REFERENCES researcher_link(rese_link_id, rese_link_gend),
   CONSTRAINT FK_LINK_FIG_GEND_FIG FOREIGN KEY(link_fig_gend_fig)
      REFERENCES gender(gend_id),
   CONSTRAINT FK_LINK_FIG_GEND_LINK FOREIGN KEY(link_fig_gend_link)
      REFERENCES gender(gend_id)
);




Mapping

Code:
   @ManyToMany
   @JoinTable(name = "link_figures",
         joinColumns = { @JoinColumn(name = "link_fig_fig"),
                     @JoinColumn(name="link_fig_gend_fig") },
         inverseJoinColumns={@JoinColumn(name="link_fig_link"),
                        @JoinColumn(name="link_fig_gend_link") } )
   private List<ResearcherFigure> linkFigures;



Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 4 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.