Hibernate annotation with common column for foreign and primary key

11,014

Solution 1

What actually did the trick in the end was adding the following annotation:

@OneToOne(cascade = CascadeType.ALL)
@JoinColumn(name="email")
@MapsId

I removed the ForeignKey annotation, since it was disregarded when creating the table. The only effect is the naming of the constraint, which is now autogenerated by hibernate and I can live with that.

Solution 2

For a one to one you would need to specify @JoinColumn(name="user_fk") for the mapping. The @ForeignKey annotation is just there to override the name of the foreign key generated by hibernate, not to tell to hibernate wich column to use (which is the role of the @JoinColumn)

[Edit after comments]

Actually, as you are mapping on the primary key you should use the @MapsId annotation to tell hibernate you are mapping to the Id of the OneToOne associated entity. Your mapping should then become :

@OneToOne(CascadeType.ALL)
@ForeignKey(name="email")
@MapsId
Share:
11,014
Chris
Author by

Chris

Primarily a systems developer, with a strong base in Spring, Java EE, Linux and SQL. I believe strongly in the principles of self organization, writing maintainable code and the dedication to self improvement and learning.

Updated on June 05, 2022

Comments

  • Chris
    Chris almost 2 years

    I am having some issues modeling a foreign key the way I like it in hibernate 4.1.9

    I basically have the following code:

    @Entity
    @XmlRootElement
    @Table(name="User")
    public class UserVO
    {
        private String email;
    
        @Id
        @Column(name="email", unique=true, nullable=false)
        @XmlElement
        public String getEmail()
        {
            return this.email;
        }
    }
    

    and this:

    @Entity
    @XmlRootElement
    @Table(name="Authentification")
    public class AuthentificationVO
    {
        private String email;
        private UserVO user;
    
        @Id 
        @Column(name="email", unique=true, nullable=false)
        @XmlElement
        public String getEmail()
        {
            return this.email;
        }
    
        @OneToOne(cascade = CascadeType.ALL)
        @ForeignKey(name="user_fk")
        public UserVO getUser()
        {
            return this.user;
        }
    }
    

    The point of it all, is to have a column named email in both tables, which should also serve as a primary key for both the User and Authentification tables. For some reason, when I run this, Hibernate insists on adding a column to the Authentification table called user_email, but I want it to use the already existing column named email.

    I tried looking around for a solution for this and I have tried using mappedBy annotation to get it right, along with JoinColumn, but nothing seems to do the trick.

  • Chris
    Chris about 11 years
    Okay, that will get me half-way. It only seems to help if I have the Id annotation on any other element than email, but when I have the Id annotation on the same column as the fk, it fails to create a foreign key.
  • Chris
    Chris about 11 years
    I am sorry to say that the foreign key is never created, regardless if I use JoinColumn or PrimaryKeyJoinColumn as long as the Id annotation is present on the email field in the AuthentificationVO class. The tables are created fine and are populated with data, but the fk is never created.
  • benzonico
    benzonico about 11 years
    did you specified both @PrimaryKeyJoinColumn AND @ForeignKey ?
  • Chris
    Chris about 11 years
    Yes I did, both of them are present.
  • benzonico
    benzonico about 11 years
    Ok, I don't give up : from docs.jboss.org/hibernate/orm/4.1/manual/en-US/html_single/… what about : @MapsId ?
  • benzonico
    benzonico about 11 years
    and by changing the @ForeignKeyto @ForeignKey(name="email") ? I'll update the answer accordingly.
  • Chris
    Chris about 11 years
    Using the following I get a foreign key and I get a column that is both primary and foreign key, but the name of that column is wrong, it should be email, but it is user_email. @OneToOne(cascade = CascadeType.ALL) @ForeignKey(name="user_email") @MapsId
  • benzonico
    benzonico about 11 years
    @ForeignKey(name="user_email") should become @ForeignKey(name="email") i guess.
  • Chris
    Chris about 11 years
    No, that didn't help. That just changed the name of the foreign key and not the column.
  • benzonico
    benzonico about 11 years
    I am beginning to get stuck there I can point you there : stackoverflow.com/questions/314578/… or specifying an @Column on your mapping of user.
  • Chris
    Chris about 11 years
    @Column cannot be used with @OneToOne I tried a couple of things in the other thread, but that basically just got me back to where I was before, without a working foreign key.