Here the db schema
CREATE TABLE Products
(
id INT NOT NULL AUTO_INCREMENT,
category_id INT NOT NULL,
description VARCHAR(100),
pric
From the EmbeddedId
javadoc:
Relationship mappings defined within an embedded id class are not supported.
So you cannot do it this way. I don't think JPA 1 specifies a standard way to implement this (in JPA 2 there is @MapsId
but I never tried), but this is what I usually do and most implementations (I think at least Hibernate, EclipseLink and OpenJPA) support it:
Declare your primary key class using primitive types:
@Embeddable
public class OrderDetailPK implements Serializable
{
private int product;
private int order;
public OrderDetailPK() {}
...
}
Annotate your entity with @IdClass
and declare the fields using the same name but the desired types:
@Entity
@IdClass(OrderDetailPK.class)
public class OrderDetail {
@Id
@ManyToOne(cascade=CascadeType.ALL)
@JoinColumn(name="product_id", insertable=false, updatable=false)
private Product product;
@Id
@ManyToOne(cascade=CascadeType.ALL)
@JoinColumn(name="order_id", insertable=false, updatable=false)
private Order order;
...
}
(I have always kept the @Id
on the fields in the entity but I didn't recheck if they are mandatory)
When i did this before (as detailed in this question and answer), i made the fields in the embeddable ID primitives (corresponding to the ID fields of the entities referred to), and then used @MapsId in the entity. I believe this is the simplest (and dare i say correct) of meeting all the requirements: that the fields in the entity are relationships, that the fields in the ID class are primitive, that every column is mapped exactly once (the @MapsId
fields not really being mappings, but sort of aliases).
Applying that to your case, the ID class looks like:
@Embeddable
public class OrderDetailPK {
private final int productId;
private final int orderId;
public OrderDetailPK(int productId, int orderId) {
this.productId = productId;
this.orderId = orderId;
}
}
And the entity class looks like:
public class OrderDetail {
@EmbeddedId
private OrderDetailPK id;
@ManyToOne(cascade = CascadeType.ALL)
@MapsId("productId")
private Product product;
@ManyToOne(cascade = CascadeType.ALL)
@MapsId("orderId")
private Order order;
private int quantity;
private double subtotal;
public OrderDetail(Product product, Order order, int quantity, double subtotal) {
this.id = new OrderDetailPK(product.getId(), order.getId());
this.product = product;
this.order = order;
this.quantity = quantity;
this.subtotal = subtotal;
}
protected OrderDetail() {}
}
First of all OrderDetailPK
has to implement Serializable
.
For second please specify which ID's you are going to use, because you has specified columns product_id
and order_id
as insertable=false, updatable=false
(read-only).
So you need to try something like the following:
@EmbeddedId
@AttributeOverrides({
@AttributeOverride(name = "product_id",column = @Column(name = "product_id")),
@AttributeOverride(name = "listingId",column= @Column(name = "order_id"))
})
private OrderDetailPK id;
More information you may find here:
http://docs.oracle.com/javaee/6/api/javax/persistence/EmbeddedId.html
http://docs.oracle.com/javaee/6/api/javax/persistence/AttributeOverride.html