0

I may be mixing up terms, but what I call a simple entity is something like Customer or Product, i.e., a thing having its own identity and for which I'm using an Integer id.

A composed entity is something like CustomerProduct, allowing to create an m:n mapping and associate some data with it. I created

class CustomerProduct extends MyCompositeEntity {
    @Id @ManyToOne private Customer;
    @Id @ManyToOne private Product;
    private String someString;
    private int someInt;
}

and I'm getting the message

Composite-id class must implement Serializable

which lead me directly to these two questions. I trivially could implement Serializable, but this would mean to serialize Customer and Product as a part of CustomerProduct and this makes no sense to me. What I'd need is a composite key containing two Integers, just like a normal key is just one Integer.

Am I off the track?

If not, how can I specify this using just annotations (and/or code)?

Community
  • 1
  • 1
maaartinus
  • 44,714
  • 32
  • 161
  • 320

2 Answers2

2

Hibernate session objects need to be serializable, this implies all referenced objects must be serializable too. Even if your were using primitive types as a composite key, you need to add a serialization step.

You can use a composite primary key in Hibernate with the annotations @EmbeddedId or @IdClass.

With IdClass you can do the follwing (assuming your entities use integer keys):

public class CustomerProduckKey implements Serializable {
    private int customerId;
    private int productId;

    // constructor, getters and setters
    // hashCode and equals
}

@Entity
@IdClass(CustomerProduckKey.class)
class CustomerProduct extends MyCompositeEntity { // MyCompositeEntity implements Serializable
    @Id private int customerId;
    @Id private int productId;

    private String someString;
    private int someInt;
}

You primary key class must be public and must have a public no-args constructor. It also must be serializable.

You can also use @EmbeddedId and @Embeddable, which is a bit clearer and allows you to reuse the PK elsewhere.

@Embeddable
public class CustomerProduckKey implements Serializable {
    private int customerId;
    private int productId;
    //...
}

@Entity
class CustomerProduct extends MyCompositeEntity {
    @EmbeddedId CustomerProduckKey customerProductKey;

    private String someString;
    private int someInt;
}
rafikn
  • 383
  • 1
  • 5
0

You can use @EmbeddedId and @MapsId:

@Embeddable
public class CustomerProductPK implements Serializable {
    private Integer customerId;
    private Integer productId;
    //...
}

@Entity
class CustomerProduct {
    @EmbeddedId
    CustomerProductPK customerProductPK;

    @MapsId("customerId")
    @ManyToOne
    private Customer;

    @MapsId("productId")
    @ManyToOne
    private Product;

    private String someString;
    private int someInt;
}
Dragan Bozanovic
  • 23,102
  • 5
  • 43
  • 110