autoincrement id没有使用JPA反映在复合键中

时间:2011-01-27 07:29:47

标签: orm jpa eclipselink

我有一个下面的映射

@Entity
@Table(name = "auctions")
public class Auction{
.
.
    @OneToMany(cascade = CascadeType.ALL, mappedBy = "auction")
    private List<AuctionParamValue> auctionParamValueList;
.
.
}


@Entity
@Table(name = "auction_param_values")
public class AuctionParamValue {

    @EmbeddedId
    protected AuctionParamValuePK auctionParamValuePK;

    @JoinColumn(name = "auction_param_id", referencedColumnName = "auction_param_id",updatable=false,insertable=false)
    @ManyToOne @MapsId("auctionParamId")
        private AuctionParam auctionParam;

    @JoinColumn(name = "auction_id", referencedColumnName  = "auction_id",updatable=false,insertable=false)
    @ManyToOne @MapsId("auctionId") 
        private Auction auction;
}

@Embeddable
public class AuctionParamValuePK {

@Id
@Basic(optional = false)
       @Column(name = "auction_id")
       @Nullable
       private Long auctionId = null;

@Id
       @Basic(optional = false)
       @Column(name = "auction_param_id")
       @Nullable
       private Long auctionParamId = null;    
}

@Entity
@Table(name = "auction_params")    
public class AuctionParam {
    @OneToMany(cascade = CascadeType.ALL, mappedBy = "auctionParam")
    private List<AuctionTypeParam> auctionTypeParamList;

    @OneToMany(cascade = CascadeType.ALL, mappedBy = "auctionParam")
    private List<AuctionParamValue> auctionParamValueList;
 }

}

当我尝试坚持拍卖时(我手动设置auctionParamId并期望auctionId自动设置(可能是最后插入的id))

但我收到以下错误,我不知道为什么查询中的auctionId在拍卖中变为0而不是最新的ID。(我使用的是eclipselink jpa提供商)

Internal Exception: com.mysql.jdbc.exceptions.MySQLIntegrityConstraintViolationException: Cannot add or update a child row: a foreign key constraint fails (`portaldemo`.`auction_param_values`, CONSTRAINT `auction_param_values_auction_id_fk` FOREIGN KEY (`auction_id`) REFERENCES `auctions` (`auction_id`))
Error Code: 1452
Call: INSERT INTO auction_param_values (auction_param_val, create_ts, last_updt_ts, auction_param_id, auction_id) VALUES (?, ?, ?, ?, ?)
    bind => [2011-02-12 04:00:00, 2011-01-27 12:02:00.28, 2011-01-27 12:17:43.25, 2, 0]
Query: InsertObjectQuery(com.eaportal.domain.AuctionParamValue[auctionParamValuePK=com.eaportal.domain.AuctionParamValuePK[auctionId=0, auctionParamId=2]])

此处 [auctionId = 0 始终为0,而​​不是最后插入的ID :(

这种映射有什么问题?

2 个答案:

答案 0 :(得分:2)

@GeneratedValue只会设置它被注释的属性的值,如果你在其他类中有其他属性引用你负责设置它们的id。

即。您需要先保留并刷新Auction,然后使用其generate Id创建AuctionParamValue。

或者,如果您使用TABLE或SEQUENCE id生成,那么您只需要调用persist,而不是flush。一般来说,我绝不会推荐IDENTITY排序,因为它的值无法预先分配。

但实际上你不应该有重复的字段。完全删除@EmbeddedId auctionParamValuePK,只需将@Id添加到两个@ManyToOnes,然后使用@IdClass。即使IDENTITY id生成,这也会使事情变得更加简单并且正常工作。

你也可以在两个@ManyToOne映射上删除insertable / updateable = false,而是将它们放在@EmbeddedId属性上,这将从关系中写入外键,但你的对象在内存中仍会被破坏

请参阅, http://en.wikibooks.org/wiki/Java_Persistence/Identity_and_Sequencing#Primary_Keys_through_OneToOne_and_ManyToOne_Relationships

答案 1 :(得分:0)

您可以尝试两件事:

  • 使两个id可以为空:使用包装器类型而不是基元(Integer,Long),并在保存之前将其设置为null
  • 保存时,将组合的主ID字段(auctionParamValuePK)保留为空(null)。

我不知道这是否可以解决问题,但我确信您至少需要执行其中一项才能解决问题。