6

I have this two table on the database revisions and Pagu

in the Pagu model, i have to composite key:

  • id int (autogenerated by database)
  • revision_id (foreign_key to revisions) table

how to implement this on Hibernate 3 ?

this is what i came up with

@Entity
@Table(name="pagu"
    ,schema="dbo"
    ,catalog="dbname"
)
@IdClass(PaguId.class)
public class Pagu  implements java.io.Serializable {

 private int id;
 private int revisiId;
 private Entitas entitas;
 private Revisi revisi;
 ...

 @Id
 @GeneratedValue
 @Column(name="id", unique=true, nullable=false)
 public int getId() {
     return this.id;
 }

 public void setId(int id) {
     this.id = id;
 }

 @Id
 @Column(name="revisi_id", unique=true, nullable=false)
 public int getRevisiId() {
     return this.revisiId;
 }

 public void setRevisiId(int id) {
     this.id = id;
 }

And this is my PaguId class

@Embeddable
public class PaguId  implements java.io.Serializable {


     private int id;
     private int revisiId;

    public PaguId() {
    }

    public PaguId(int id, int revisiId) {
       this.id = id;
       this.revisiId = revisiId;
    }

    @Column(name="id", nullable=false)
    public int getId() {
        return this.id;
    }

    public void setId(int id) {
        this.id = id;
    }

    @Column(name="revisi_id", nullable=false)
    public int getRevisiId() {
        return this.revisiId;
    }

    public void setRevisiId(int revisiId) {
        this.revisiId = revisiId;
    }


   public boolean equals(Object other) {
         if ( (this == other ) ) return true;
         if ( (other == null ) ) return false;
         if ( !(other instanceof PaguId) ) return false;
         PaguId castOther = ( PaguId ) other; 

         return (this.getId()==castOther.getId() && this.getRevisiId()==castOther.getRevisiId())
 && (this.getRevisiId()==castOther.getRevisiId());
   }

   public int hashCode() {
         int result = 17;

         result = 37 * result + this.getId();
         result = 37 * result + this.getRevisiId();
         return result;
   }   


}

When I try to save this on database I got error :

org.hibernate.NonUniqueObjectException: a different object with the same    identifier value was already associated with the session:

-- UPDATE-- But changing the implementation using EmbeddedId like this

public class Pagu  implements java.io.Serializable {


     private PaguId id;
     ...

     @EmbeddedId
@AttributeOverrides( {
    @AttributeOverride(name="id", column=@Column(name="id", nullable=false) ), 
    @AttributeOverride(name="revisiId", column=@Column(name="revisi_id", nullable=false) ) } )
public PaguId getId() {
    return this.id;
}

public void setId(PaguId id) {
    this.id = id;
}
....

It compiled right, but gave me error when persist the model.

org.hibernate.id.IdentifierGenerationException: ids for this class must be manually assigned before calling save(): id.model.Pagu
ahmy
  • 4,095
  • 4
  • 27
  • 36
  • You should not use `@Embeddable` and `@IdClass` at the same time. Either choose to use: 1. `@Embeddable` on the composite primary key class and `@EmbeddedId` in the entity class, or 2. no annotation on the composite primary key class and `@IdClass` on the entity class level with multiple `@Id` annotations in the entity class itself (for fields). – Piotr Nowicki Nov 14 '11 at 09:30
  • Doing this also generated exception `a different object with the same identifier value was already associated with the session: [id.go.model.Pagu#id.go..model.PaguId@5ae9]` the kind error i got if there is no @GeneratedValue on the @id – ahmy Nov 14 '11 at 09:43
  • I found an link to create Partial identifier generation http://docs.jboss.org/hibernate/annotations/3.5/reference/en/html_single/#d0e1150 but also there is a warning that such a construct as fundamentally wrong – ahmy Nov 14 '11 at 09:56
  • you might be interested in creating your own ID generating mechanism. [http://onjava.com/pub/a/onjava/2006/09/13/dont-let-hibernate-steal-your-identity.html?page=1] this will let you remove the `@GeneratedValue` annotation – Piotr Nowicki Nov 14 '11 at 10:03

2 Answers2

3

I do not think it is possible to use GeneratedValue in a composite key, you have to choose either a composite key, or a single GeneratedValue-id.

Rasmus Franke
  • 4,434
  • 8
  • 45
  • 62
0

you have to remove both your keys id and revisiId from your main Entity class as it is already present in the @Embeddable, try and share your response.

mprabhat
  • 20,107
  • 7
  • 46
  • 63
  • You can find one working example [at](http://j2eereference.com/2011/01/implementing-composit-primary-key-with-jpa-and-hibernate/), quite nicely explained. – mprabhat Nov 14 '11 at 09:21
  • can you compare your code with the one mentioned in my previous comment (http://j2eereference.com/2011/01/implementing-composit-primary-key-with-jpa-and-hibernate/). – mprabhat Nov 14 '11 at 09:27
  • I updated the code to conform with your example and add @EmbeddableId. this is the original form when i reverse engineer the model from database using netbeans – ahmy Nov 14 '11 at 09:36
  • With Composite Key you have to provide your own value (http://docs.jboss.org/hibernate/stable/core/reference/en-US/html/components.html#components-compositeid) – mprabhat Nov 14 '11 at 10:03