Two foreign keys as primary key

2020-08-22 07:30发布

问题:

How would I implement the following tables using hibernate annotations?

Current code is: (stripped for brevity)

User

@Entity
@Table(name = "user")
public class User implements java.io.Serializable {
    @Id
    @GeneratedValue
    public Long getId() {
        return id;
    }
}

SocialNetwork

@Entity
@Table(name = "social_network")
public class SocialNetwork implements java.io.Serializable {
    @Id
    @GeneratedValue
    public int getId() {
        return id;
    }
}

SocialProfile

@Entity
@Table(name = "social_profile")
public class SocialProfile implements java.io.Serializable {
    @Id
    @ManyToOne
    @JoinColumn(name="user_id")
    public User getUser() {
        return user;
    }

    @Id
    @ManyToOne
    @JoinColumn(name="social_network_id")
    public SocialNetwork getSocialNetwork() {
        return socialNetwork;
    }
}

Obviously my code is not working correctly right now. Can anyone shed some light onto this?

回答1:

you need an embeddable SocialProfileId like this :

@Embeddable
public class SocialProfileId implements Serializable {
    @Column(name = "user_id")
    private long userId;
    @Column(name = "social_network_id")
    private long socialNetworkId;
}

then, your SocialProfile entity will look like this :

@Entity
@Table(name = "social_profile")
public class SocialProfile implements java.io.Serializable {

    @EmbeddedId
    private SocialProfileId id;

    @ManyToOne
    @JoinColumn(name="user_id")
    public User getUser() {
        return user;
    }

    @ManyToOne
    @JoinColumn(name="social_network_id")
    public SocialNetwork getSocialNetwork() {
        return socialNetwork;
    }
}

EDIT sorry, i have mixed annotations on fields and methods on my answer ... never do that ! ;-)



回答2:

It seems you need mamy-to-many mapping having join-table with extra column. For this you need to create 2 more classes.

FYI : http://www.mkyong.com/hibernate/hibernate-many-to-many-example-join-table-extra-column-annotation/



回答3:

My problem for a REST application was similar but a little bit different, I will post it here. I had 2 data tables: Song & Tag with an id each (songid, tagid). Then I had a table for joining them together Tagassignment which only had both of the primary keys from Song and Tag. So I did not want to join them, I wanted to keep the table with both foreign keys.

Source of my solution: http://www.objectdb.com/java/jpa/entity/id


Before

Song

@Entity
@Table(name = "songs")
data class Song(

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    val id: Int,

    ...
)

Tag

@Entity
@Table(name = "tags")
data class Tag(

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    val id: Int,

    ...
)

Tagassignment

 @Entity
 @Table(name = "tagassignment")
 data class Tagassignment(

     val songid: Int,

     val tagid: Int

 )

After

I did not change Song and Tag.

Tagassignment

@Entity
@IdClass(value = TagassignmentKey::class)
@Table(name = "tagassignment")
data class Tagassignment(

    @Id
    val songid: Int,

    @Id
    val tagid: Int

)

and I created a Key class

TagassignmentKey

class TagassignmentKey(val songid: Int, val tagid: Int) : Serializable {

    constructor() : this(0, 0)

}


回答4:

In addition to what Pras has said, we can even move the @ManyToOne inside the @Embeddable class itself so SocialProfileId will look like, where you can clearly see in your Embedded class itself that it referencing another table

@Embeddable
public class SocialProfileId implements Serializable {

    @ManyToOne
    @JoinColumn(name = "user_id")
    private User userId;


    @ManyToOne
    @JoinColumn(name = "social_network_id")
    private SocialNetwork socialNetworkId;

    public SocialProfileId(User userId, SocialNetwork socialNetworkId) {
        this.userId = userId;
        this.socialNetworkId = socialNetworkId;
    }

}

And your SocialProfile entity can simply have the embedded class and other fields like email and so on..

@Entity
@Table(name = "social_profile")
public class SocialProfile implements java.io.Serializable {

    @EmbeddedId
    private SocialProfileId id;

    @Column(name="email")
    private String email;
}