问题
Hello I'm trying to make an example of persistence of a OneToMany relationship in which I get the following error:
Exception Description: Invalid composite primary key specification. The names of the primary key fields or properties in the primary key class [entitys.OrderItemPK] and those of the entity bean class [class entitys.OrderItem] 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.
Note: I'm using EclipseLink and MySQL DB
The entities:
@Entity
public class CustomerOrder implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Basic(optional = false)
@Column(name = "idOrder")
private Integer idOrder;
@Basic(optional = false)
@Column(name = "orderText")
private String orderText;
@OneToMany(cascade = CascadeType.ALL, mappedBy = "customerOrder")
private Collection<OrderItem> orderItemCollection;
public CustomerOrder() {
}
}
@Entity
@IdClass(OrderItemPK.class)
public class OrderItem implements Serializable {
private static final long serialVersionUID = 1L;
@EmbeddedId
protected OrderItemPK orderItemPK;
@Basic(optional = false)
@Column(name = "itemDesc")
private String itemDesc;
@Id
@ManyToOne(optional = false)
@JoinColumns({
@JoinColumn(name="idOrder", referencedColumnName="idOrder"),
@JoinColumn(name="ItemNumber", referencedColumnName="ItemNumber")
})
//@JoinColumn(name = "idOrder", referencedColumnName = "idOrder", insertable = false, updatable = false)
private CustomerOrder customerOrder;
private CustomerOrder customerOrder;
public OrderItem() {
this.orderItemPK = new OrderItemPK();
}
}
@Embeddable
public class OrderItemPK implements Serializable {
@Basic(optional = false)
@Column(name = "idOrder")
private int idOrder;
@Basic(optional = false)
@Column(name = "itemNumber")
private int itemNumber;
public OrderItemPK() {
}
}
The test Source:
public static void main(String[] args) {
factory = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
EntityManager em = factory.createEntityManager();
em.getTransaction().begin();
// Fill the items fileds
OrderItem item = new OrderItem();
item.setItemDesc("Item Text");
// Fill the orders fields
CustomerOrder order = new CustomerOrder();
order.setOrderText("Order text");
// Fill the relationship fields
order.getOrderItemCollection().add(item);
item.setCustomerOrder(order);
em.persist(order);
em.getTransaction().commit();
}
I have no idea what I'm doing wrong, any suggestions are welcome.
回答1:
Well i managed to solve the problem by removing idClass annotation and adding the @MapId
heres the final code:
@Entity
@Table(name = "Orders")
public class CustomerOrder implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Basic(optional = false)
@Column(name = "idOrder")
private Integer idOrder;
@Basic(optional = false)
@Column(name = "orderText")
private String orderText;
@OneToMany(mappedBy = "customerOrder", cascade = CascadeType.ALL)
private Collection<OrderItem> orderItemCollection;
public CustomerOrder() {
}
@Entity
@Table(name = "OrdersItems")
public class OrderItem implements Serializable {
private static final long serialVersionUID = 1L;
@EmbeddedId
protected OrderItemPK orderItemPK;
@Basic(optional = false)
@Column(name = "itemDesc")
private String itemDesc;
@MapsId("idOrder")
@ManyToOne(optional = false)
@JoinColumn(name = "idOrder", referencedColumnName = "idOrder", nullable = false)
private CustomerOrder customerOrder;
public OrderItem() {
this.orderItemPK = new OrderItemPK();
}
@Embeddable
public class OrderItemPK implements Serializable {
@Basic(optional = false)
@Column(name = "idOrder")
private int idOrder;
@Basic(optional = false)
@Column(name = "itemNumber")
private int itemNumber;
public OrderItemPK() {
}
public static void main(String[] args) {
factory = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
EntityManager em = factory.createEntityManager();
em.getTransaction().begin();
// Fill the order item
OrderItem item = new OrderItem();
item.getOrderItemPK().setItemNumber(1);
item.setItemDesc("Product Name");
// Fill the order
CustomerOrder order = new CustomerOrder();
order.setOrderText("Testing");
// Create relationship
order.getOrderItemCollection().add(item);
item.setCustomerOrder(order);
// Persist
em.persist(order);
em.getTransaction().commit();
}
But i can't get it work with IdClass, here's the source
@Embeddable
public class OrderItemPK implements Serializable {
@Basic(optional = false)
@Column(name = "idOrder")
private Integer idOrder;
@Basic(optional = false)
@Column(name = "ItemNumber")
private Integer itemNumber;
public OrderItemPK() {
}
@Entity
@IdClass(OrderItemPK.class)
public class OrderItem implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@Column(name = "itemNumber")
private Integer itemNumber;
@Basic(optional = false)
@Column(name = "itemDesc")
private String itemDesc;
@MapsId("idOrder")
@ManyToOne(optional = false)
@JoinColumn(name = "idOrder", referencedColumnName = "idOrder", nullable = false)
private CustomerOrder customerOrder;
public OrderItem() {
}
@Entity
public class CustomerOrder implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Basic(optional = false)
@Column(name = "idOrder")
private Integer idOrder;
@Basic(optional = false)
@Column(name = "OrderText")
private String orderText;
@OneToMany(mappedBy = "customerOrder", cascade = CascadeType.ALL)
private Collection<OrderItem> orderItemCollection;
public CustomerOrder() {
this.orderItemCollection = new ArrayList();
}
回答2:
Use MapsId in OrderItem:
@Entity
public class OrderItem implements Serializable {
private static final long serialVersionUID = 1L;
@EmbeddedId
protected OrderItemPK orderItemPK;
@Basic(optional = false)
@Column(name = "itemDesc")
private String itemDesc;
@MapsId("idOrder")
@ManyToOne(optional = false)
@JoinColumn(name = "idOrder", referencedColumnName = "idOrder")
private CustomerOrder customerOrder;
}
An alternative is to remove the embedded id and use an ID class:
@Entity
@IdClass(OrderItemPK.class)
public class OrderItem implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@Column(name = "itemNumber")
private int itemNumber;
@Basic(optional = false)
@Column(name = "itemDesc")
private String itemDesc;
@Id
@ManyToOne(optional = false)
@JoinColumn(name = "idOrder", referencedColumnName = "idOrder")
private CustomerOrder customerOrder;
}
public class OrderItemPK implements Serializable {
//name of the relation in the entity, but same type as the CustomerOrder PK.
int customerOrder;
int itemNumber;
public OrderItemPK() {
}
}
来源:https://stackoverflow.com/questions/29012099/jpa-eclipselink-onetomany-derived-ids-fail