Hibernate查找错误的主键

时间:2013-04-09 08:48:27

标签: java spring hibernate spring-data-jpa

我的实体有两个外键,其中一个是主键。我在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,价格)

我需要更改哪些内容才能找到相应“文章”对象的“采购”记录?

2 个答案:

答案 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() - 方法存根只包含主键的一部分。它“无法解析路径上的属性”。欢迎您发表评论!