我正在使用 JPA 实体实现以下表结构,其中显示的属性代表 PK/FK 列。 protocolId 是自动生成的,并在调用 persist()
之前在所有实体中设置为 null。整个结构被立即存储。
与 help of a stackoverflow user和 JPA spec ,我解析了 Position
中的派生身份:
@Entity
@Table(name="...")
@IdClass(PositionID.class)
public class Position {
@Id
@Column(name = "POSITION_ID")
private int positionId;
@Id
@ManyToOne(...)
@JoinColumn(name="PROTOCOL_ID")
private Protocol protocol;
@OneToMany(mappedBy="position")
private Collection<Item>
}
public class PositionID implements Serializable{
private int protocol;
private int positionId;
}
上述关系有效,但我在 Item
中实现派生标识时遇到问题。
这是我根据2.4.1.3派生身份示例章节中的规范编写的版本:
@Entity
@Table(name="...")
@IdClass(ItemId.class)
public class Item {
@Id
@Column(name = "ITEM_NAME")
private String itemName;
@Id
@ManyToOne(...)
@JoinColumns({
@JoinColumn(name="POSITION_ID", referencedColumnName="POSITION_ID"),
@JoinColumn(name="PROTOCOL_ID", referencedColumnName="PROTOCOL_ID")
})
private Position position;
}
public class ItemId implements Serializable {
private String itemName;
private PositionId position;
}
不幸的是,这会导致以下错误:
Invalid composite primary key specification. The names of the primary key fields or properties in the primary key class [null] and those of the entity bean class [class ......Item] must correspond and their types must be the same.
如何实现Item
的身份?
最佳答案
我认为你可以使用组合主键!
在您的主要实体(项目)中,您使用以下内容:
@EmbeddedId
private CombinedPK id;
并在CombinedPK中设置:
@Embeddable // Annotation on class level
public class CombinedPK {
...
@Column(name = "positionId")
private Integer positionId;
@Column(name = "protocolId")
private Integer protocolId;
}
然后可以像平常一样映射组合PK中的列,每个列都有自己。
此外,从您的 position
字段中删除 @Id
注释,并将 insertable=false, updatable=false
添加到您的 @ JoinColumn
注释。
问题在于,在 Java 模型中,您拥有(并且需要)来自 SQL 的相同数据的两种不同表示形式:您需要对主键进行建模和注释,还需要外键关系。 JPA 不能很好地处理这个问题,并且 JPA 还禁止更改记录的主键。如果您可以更改数据库,您会发现添加 'SERIAL' 更容易列添加到您的项目表中,并将其用作主键(并在外键列上添加复合唯一约束)。
关于java - JPA:如何使用派生 IdClass 实现复合主键?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32651686/