问题
This is a situation I want to represent in my PLAY project:
table clients {
client_id (pk),
description
}
table items {
client_id (fk, pk),
item_id (pk)
}
In the 'items' table I want to have a composite primary key that will consist of combined client_id and item_id. I have read JPA documentation as well as many posts on the topic but everything fails again and again. This is one of many versions I have tried - closest to the JPA documentation.
@Entity
@Table(name = "items")
public class Items extends Model {
ItemsPK primaryKey;
public Items() {
}
@EmbeddedId
public ItemsPK getPrimaryKey() {
return primaryKey;
}
public void setPrimaryKey(ItemsPK pk) {
primaryKey = pk;
}
}
@Embeddable
public class ItemsPK implements Serializable {
private long itemId;
private Client client;
public ItemsPK() {
}
@Column(name = "item_id")
@GeneratedValue(strategy = GenerationType.AUTO)
public long getItemId() {
return itemId;
}
public void setItemId(long itemId) {
this.itemId = itemId;
}
@ManyToOne
@JoinColumn(name = "client_id", nullable = false)
public Client getClient() {
return client;
}
public void setClient(Client client) {
this.client = client;
}
//public int hashCode() {...
//public boolean equals(Object obj) {...
}
The above code (as well as many other different setups) produce following error during play launch:
java.lang.RuntimeException: Error reading annotations for models.ItemsPK at com.avaje.ebeaninternal.server.deploy.parse.ReadAnnotations.readAssociations(ReadAnnotations.java:73) ~[ebean.jar:na] at com.avaje.ebeaninternal.server.deploy.BeanDescriptorManager.readDeployAssociations(BeanDescriptorManager.java:1100) ~[ebean.jar:na]
I don't have a clue what might be wrong with my code. I'm starting to think that it is a PLAY bug. Any ideas?
回答1:
Cześć,
This not an answer, rather suggestion. Can you tell me what is main goal of using composite PK in your case? Your both models would be reaaaaly small and easy with Ebean ORM
models/Client.java
package models;
import play.db.ebean.Model;
import javax.persistence.Entity;
import javax.persistence.Id;
@Entity
public class Client extends Model {
@Id
public Long id;
public String description;
}
models/Item.java
package models;
import play.db.ebean.Model;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
@Entity
public class Item extends Model {
@Id
public Long id;
@ManyToOne
public Client client;
}
and that's all. It gives you what you need except the composite PK
回答2:
In my experience, you are not able to use GeneratedValue inside an EmbeddedId, the values in a composite key must be assigned. See excerpt below.
The use of the GeneratedValue annotation is only required to be supported for simple primary keys. Use of the GeneratedValue annotation is not supported for derived primary keys.
http://docs.oracle.com/javaee/6/api/javax/persistence/GeneratedValue.html
http://www.objectdb.com/api/java/jpa/GeneratedValue
I would recommend not using a composite key for this as itemId
would be sufficient in generating a unique identifier.
回答3:
I think that you haven't disabled Ebean. Ebean is the default ORM for Play 2. If you want to use JPA you have to disable Ebean.
So in your Build.scala, add this:
val main = PlayProject(appName, appVersion, appDependencies, mainLang = JAVA).settings(
ebeanEnabled := false
)
And in your application.conf edit this line:
ebean.default="models.*"
来源:https://stackoverflow.com/questions/10723465/cant-create-composite-primary-key-with-foreign-key-in-play-2-0