TAGS :Viewed: 18 - Published at: a few seconds ago

[ Unable to use inherited composite key as derived id in JPA2 ]

Am I doing something wrong or is this not supported in JPA2/eclipselink, let me explain by code;

 @Embeddable
public class MemberID implements Serializable {
    private String e_mail;
    private String password;
        //...no-arg constructor, getter and setter

the entity below uses MemberID as composite key

@Entity
@Table(name="MEMBER_DETAILS")
@Inheritance(strategy=InheritanceType.JOINED)
@DiscriminatorColumn(name="GROUPNAME", discriminatorType=DiscriminatorType.STRING,   length=20)
public class Member_Details implements Serializable {

@EmbeddedId
private MemberID memberIdentity;
...other code

the entity below extends Member_Details and therefore inherits its key

@Entity
@Table(name="INDIVIDUAL_USER")
@DiscriminatorValue("INDIVIDUAL_USER")
public class Individual_User extends Member_Details implements Serializable {    
    @OneToMany(mappedBy="userinfo", fetch=FetchType.EAGER)
private List<UserComment> userComments = new ArrayList<UserComment>();
... other code

the following is a composite key that contains MemberID as part of it.

@Embeddable
public class CommentID implements Serializable { 
private MemberID memberId;
@Temporal(TemporalType.TIMESTAMP)
@Column(name="TIME_POSTED")
private Date timeOfComment;
...other code

the entity below uses CommentID as its composite key. I want it to be dependent on the entity Individual_User, and therefore use a derived id.That is why MemberID is part of its composite key.

@Entity
@Table(name="USER_COMMENTS")
public class UserComment implements Serializable {
private static final long serialVersionUID = 1L;
@EmbeddedId
private CommentID commentIdentity;

@MapsId("memberId")
@ManyToOne
@JoinColumns({
@JoinColumn(name="E_MAIL", referencedColumnName="E_MAIL"),
@JoinColumn(name="PASSWORD", referencedColumnName="PASSWORD")
})
private Individual_User userinfo;
...other code

The problem comes when I try to deploy, the following exception is thrown:

Caused by: Exception [EclipseLink-7321] (Eclipse Persistence Services - 2.3.0.v20110604-r9504): org.eclipse.persistence.exceptions.ValidationException
Exception Description: The field [MEMBER_DETAILS.PASSWORD] from the derived id mapping  [userinfo] from class [kariro.semaplace.talk.entities.UserComment] is an invalid id field from the reference class [kariro.semaplace.registration.entity.Individual_User]. Ensure there is a corresponding id mapping to that field. 

But when I change the @ManyToOne relationship from UserComment to reffer to type Member_Details instead of its subtype Individual_User, it works with no problems, but I am afraid this will bring in more problems later, or compromise the functioning of the app. I really don't know whether eclipselink does not allow inherited ids to be used as derived ids or am doing something wrong. someone please help me out.

Answer 1


I'm not sure why you are getting the error, but you could avoid the issue entirely by simplifying your entities.

  1. The first thing that jumps out to me is the fact that your user's PK includes password. Passwords are generally changeable, primary keys are not. Also, would you ever expect to have two distinct users with the same email but different passwords? Probably not. Drop MemberID and change Member_Details to have a simple @Id of just e_mail instead:

    @Entity
    @Table(name="MEMBER_DETAILS")
    @Inheritance(strategy=InheritanceType.JOINED)
    @DiscriminatorColumn(name="GROUPNAME", discriminatorType=DiscriminatorType.STRING, length=20)
    public class Member_Details implements Serializable
    {
      @Id
      private String e_mail;
      private String password;
      // ...
    }
    

    CommentID would change also:

    @Embeddable
    public class CommentID implements Serializable
    {
      private String e_mail;
    
      @Temporal(TemporalType.TIMESTAMP)
      @Column(name="TIME_POSTED")
      private Date timeOfComment;
    }
    

    And the @MapsId on UserComment would change to @MapsId("e_mail").

  2. The changes above should be enough to avoid your issue, but if it were me, I would get rid of the composite primary key on UserComment as well. To simply things, you could give it a UUID and then put a unique constraint on e_mail and timeOfComment.