maaartinus
maaartinus

Reputation: 46482

Hibernate composed entity

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)?

Upvotes: 0

Views: 327

Answers (2)

Dragan Bozanovic
Dragan Bozanovic

Reputation: 23562

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;
}

Upvotes: 0

rafikn
rafikn

Reputation: 383

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;
}

Upvotes: 2

Related Questions