persistence@glassfish.java.net

Re: Composite Primary Key Mapping error - Invalid composite primary key specification

From: sudhakar <sudhakar_at_co.brazos.tx.us>
Date: Wed, 12 Sep 2007 23:17:57 -0500

I found the issue. The @Id annotation in the owning class
(VelocityUserDefinedField.java) had to be directly on or above the
field. So where I initially had

    @Id
    @Column(name = "FieldNo")
    private int fieldNo;

    @Id
    @Column(name = "UserID", nullable = false, insertable = false,
updatable = false)
    private int userId;

when I changed it to

    @Column(name = "FieldNo")
    @Id
    private int fieldNo;

    @Column(name = "UserID", nullable = false, insertable = false,
updatable = false)
    @Id
    private int userId;


The error went away. I was able to reproduce it in a different project.
If someone else can replicate this also, I could file a bug if this is one.
Thanks
-sud

wrote:
> I'm following the detailed example posted on this page as the 5th post
> by ss141213 and have been unable to successfully replicate it in my
> own code.
>
> http://forums.java.net/jive/thread.jspa?threadID=14559
>
> My classes are as below:
>
> This is my Composite Primary Key class (VelocityUserDefinedFieldPK.java):
>
> public class VelocityUserDefinedFieldPK implements Serializable {
> private static final long serialVersionUID = -2079169439511686165L;
>
> private int userId;
> private int fieldNo;
>
> public VelocityUserDefinedFieldPK() {
> }
>
> public VelocityUserDefinedFieldPK(int userId, int fieldNo) {
> this.userId = userId;
> this.fieldNo = fieldNo;
> }
>
> @Override
> public boolean equals(Object otherOb) {
> if (this == otherOb) {
> return true;
> }
> if (!(otherOb instanceof VelocityUserDefinedFieldPK)) {
> return false;
> }
> VelocityUserDefinedFieldPK other =
> (VelocityUserDefinedFieldPK) otherOb;
> return (userId == 0 ? other.userId == 0 : userId == other.userId)
> && fieldNo == other.fieldNo;
> }
>
> @Override
> public int hashCode() {
> int hash = 7; // arbitrary
> hash = 31 * hash + userId;
> hash = 31 * hash + (fieldNo == 0 ? 0 : fieldNo);
> return hash;
> }
>
> @Override
> public String toString() {
> return "" + userId + "-" + fieldNo;
> }
> }
>
> This is the owning class in the Many to One relationship
> (VelocityUserDefinedField.java):
>
> @Entity
> @IdClass(brazos.ldap.ejb.jobs.domain.VelocityUserDefinedFieldPK.class)
> @Table(name = "UserDefinedFields")
> public class VelocityUserDefinedField implements Serializable {
>
> private static final long serialVersionUID = 6690178500638415700L;
>
> @Id
> @Column(name = "FieldNo")
> private int fieldNo;
>
> @ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER,
> optional = false)
> @JoinColumn(name = "UserID", referencedColumnName = "HostUserId",
> nullable = false)
> private VelocityUser user;
>
> @Id
> @Column(name = "UserID", nullable = false, insertable = false,
> updatable = false)
> private int userId;
>
> @Column(name = "Value")
> private String value;
>
> public VelocityUserDefinedField() {
> }
>
> public VelocityUserDefinedField(VelocityUser user, int fieldNo,
> String value) {
> this.fieldNo = fieldNo;
> this.value = value;
> this.user = user;
> userId = user.id;
> }
>
> public VelocityUser getUser() {
> return user;
> }
>
> public void setUser(VelocityUser user) {
> this.user = user;
> }
>
> public String getValue() {
> return value;
> }
>
> public void setValue(String value) {
> this.value = value;
> }
>
> public int getFieldNo() {
> return fieldNo;
> }
>
> public void setFieldNo(int fieldNo) {
> this.fieldNo = fieldNo;
> }
>
> public int getUserId() {
> return userId;
> }
>
> public void setUserId(int userId) {
> this.userId = userId;
> }
>
> }
>
> This is the inverse class in the Many to One relationship
> (VelocityUser.java):
>
> @Table(name = "Users")
> @Entity
> public class VelocityUser implements Serializable {
>
> private static final long serialVersionUID = -7002789763335653579L;
>
> @Id
> @GeneratedValue(strategy = GenerationType.IDENTITY)
> @Column(name = "HostUserId")
> int id;
>
> @Column(name = "FirstName")
> String firstName;
>
> @Column(name = "LastName")
> String lastName;
>
> @OneToMany(cascade = CascadeType.ALL, mappedBy = "user")
> Set<VelocityUserDefinedField> userDefinedFields;
>
> public VelocityUser() {
> }
>
> public String getFirstName() {
> return firstName;
> }
>
> public void setFirstName(String firstName) {
> this.firstName = firstName;
> }
>
> public String getLastName() {
> return lastName;
> }
>
> public void setLastName(String lastName) {
> this.lastName = lastName;
> }
>
> public int getId() {
> return id;
> }
>
> public Set<VelocityUserDefinedField> getUserDefinedFields() {
> return userDefinedFields;
> }
>
> public void setUserDefinedFields(
> Set<VelocityUserDefinedField> userDefinedFields) {
> this.userDefinedFields = userDefinedFields;
> }
> }
>
>
>
> When I attempt to call any of the persistence methods I get the
> following error message:
>
> Internal Exception: javax.persistence.PersistenceException: Exception
> [TOPLINK-28018] (Oracle TopLink Essentials - 2.0 (Build b58g-fcs
> (09/07/2007))):
> oracle.toplink.essentials.exceptions.EntityManagerSetupException
> Exception Description: predeploy for PersistenceUnit [velocityPU] failed.
> Internal Exception: Exception [TOPLINK-7150] (Oracle TopLink
> Essentials - 2.0 (Build b58g-fcs (09/07/2007))):
> oracle.toplink.essentials.exceptions.ValidationException
> Exception Description: Invalid composite primary key specification.
> The names of the primary key fields or properties in the primary key
> class [brazos.ldap.ejb.jobs.domain.VelocityUserDefinedFieldPK] and
> those of the entity bean class [class
> brazos.ldap.ejb.jobs.domain.VelocityUserDefinedField] must correspond
> and their types must be the same. Also, ensure that you have specified
> id elements for the corresponding attributes in XML and/or an @Id on
> the corresponding fields or properties of the entity class.
> at
> oracle.toplink.essentials.exceptions.PersistenceUnitLoadingException.exceptionSearchingForPersistenceResources(PersistenceUnitLoadingException.java:143)
> at
> oracle.toplink.essentials.ejb.cmp3.EntityManagerFactoryProvider.createEntityManagerFactory(EntityManagerFactoryProvider.java:169)
> at
> javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:110)
> at
> javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:83)
>
>
> As you will notice the fields in the Primary Key class,
> VelocityUserDefinedFieldPK.java (userId and fieldNo - both int type)
> do match the fields in the entity class (VelocityUserDefinedField.java).
>
> I'd appreciate any help in troubleshooting this.
> Thanks
>
> -sud
>
> ------------------------------------------------------------------------
> Tonight's top picks. What will you watch tonight? Preview the hottest
> shows
> <http://us.rd.yahoo.com/tv/mail/tagline/tonightspicks/evt=48220/*http://tv.yahoo.com/%20>
> on Yahoo! TV.