我的实体有两个外键,其中一个是主键。我在JPA Wiki中读到,如果孩子的(采购)主键与父母的(物品)主键相同,则建立@OneToOne关系。
@SuppressWarnings("serial")
@Entity
public class Procurement implements Serializable {
@Id
@OneToOne
// the child's primary key is the same as the parent
@JoinColumn(name = "articleId", referencedColumnName = "id")
private Article article;
@OneToOne
@JoinColumn(name = "supplierId", referencedColumnName = "id")
private Supplier supplier;
遵循标准方法,JpaRepository应如下所示:
@Repository
public interface IProcurementRepository extends
JpaRepository<Procurement, Article>
但是,如果我想调用提供“Article”对象的findOne方法(查找主键),Hibernate会抛出异常。
org.hibernate.TypeMismatchException:提供了错误类型的id de.willms.spring.myerp.model.Procurement。预期:上课 de.willms.spring.myerp.model.Procurement,上课了 de.willms.spring.myerp.model.Article
数据库表结构:
表“文章”(ID,shortText)
表“供应商”(ID,名称)
表“采购”(articleID,supplierID,价格)
我需要更改哪些内容才能找到相应“文章”对象的“采购”记录?
答案 0 :(得分:1)
您仍然必须使用int或long类型的id。不同之处在于,您必须使用@JoinColumn
,而不是加入@PrimaryKeyJoinColumn
。你的课应该是这样的。
@SuppressWarnings("serial")
@Entity
public class Procurement implements Serializable {
@Id
@GeneratedValue(generator = "articleForeignGenerator")
/* Hibernate-specific generator needed for shared primary key */
@GenericGenerator(name = "articleForeignGenerator", strategy = "foreign", parameters = @Parameter(name = "property", value = "article"))
@Column(name = "articleId")
private int articleId;
@OneToOne
// the child's primary key is the same as the parent
@PrimaryKeyJoinColumn
private Article article;
@OneToOne
@JoinColumn(name = "supplierId", referencedColumnName = "id")
private Supplier supplier;
请注意,我使用特定于hibernate的生成器作为ID。您的JPA提供商可能会有所不同。
答案 1 :(得分:1)
最后,我在Hibernate中发现了一个特殊的功能(令人惊讶,但在文档中很难理解),从而导致了解决方案。
只要主键由多个列组成,或者就像我的情况一样,它与其他表有关,就必须编写一个特殊的ID类。
@Embeddable
public class Procurement_ID implements Serializable {
/**
* This attribute establishes the 1:1 connection to a record in the
* "article" table. The column "articleId" is a foreign key to the column
* "id" in the {@link Article} entity. (Warning: This is Hibernate
* specific!)
*/
@OneToOne
@JoinColumn(name = "articleId", referencedColumnName = "id")
private Article article;
/**
* This attribute establishes the 1:1 connection to a record in the table
* "supplier". The column "supplierId" is a foreign key to the column "id"
* in the {@link Supplier} entity. (Warning: This is Hibernate specific!)
*/
@OneToOne
@JoinColumn(name = "supplierId", referencedColumnName = "id")
private Supplier supplier;
(由于更“标准化”的数据模型,我切换到复合主键。)
由于@Embeddable注释,可以将此ID注入实体类。
@Entity
public class Procurement implements Serializable {
/**
* The composite primary key of the underlying table is defined in the
* {@link Procurement_ID} class.
*/
@EmbeddedId
private Procurement_ID procid;
在我使用这种方法的情况下,Hibernate使用正外键检查插入一条新记录:
[DEBUG] 生成的标识符:组件[article,supplier] {article = de.willms.spring.myerp.model.Article#1,supplier = de.willms.spring.myerp.model 。供应商#1},使用策略:org.hibernate.id.CompositeNestedGeneratedValueGenerator
...(Flusing)......
[DEBUG]上市实体:...... de.willms.spring.myerp.model.Procurement {price = 2.5,deliveryTime = 10, 的 PROCID =组分[文章,供应商] {文章= de.willms.spring.myerp.model.Article#1, supplier = de.willms.spring.myerp.model.Supplier#1} ,priceUnit = $}
然而,遗憾的是JpaRepository无法注入find() - 方法存根只包含主键的一部分。它“无法解析路径上的属性”。欢迎您发表评论!