2

我们正在尝试将 Hibernate 与使用大量复合键的数据库一起使用,这让我们很头疼。不幸的是,我们不能改变模式,所以我们必须在我们的字段之间做很多额外的映射。我们仅限于使用 JPA 1.0 和 Hibernate 3.3。

到目前为止,我们遇到的最大问题是使用 2 个值的复合键来处理两个实体之间的一对一关联,其中表对这些列具有不同的名称(数据库的命名约定是每列上的特定于表的前缀。)

每当我们执行查询时,我们都会得到这个异常:

Caused by: org.hibernate.TypeMismatchException Provided id of the wrong type for class com.business.entity.InvestorIssuerEmailEntity.  
Expected: class com.business.entity.InvestorIssuerEmailEntityPK, got class com.business.entity.InvestorIssuerEntityPK; 

这些表的两个类 InvestorIssuerEntity 和 InvestorIssuerEmailEntity 有一个可选的 @OneToOne 关联(在某些情况下 InvestorIssuer 在 InvestorIssuerEmail 中没有匹配的记录):

@IdClass(InvestorIssuerEntityPK.class)
@Table(name = "T090_INVESTOR_ISSUER")
@Entity
InvestorIssuerEntity
    @Column(name = "T090_091_INVESTOR_ID", nullable = false, insertable = true, 
updatable = true, length = 18, precision = 0)
    @Id
    private Long investorId;

    @Column(name = "T090_102_ISSUER_ID", nullable = false, insertable = true, 
updatable = true, length = 18, precision = 0)
    @Id
    private Long issuerId;

(other fields omitted)

    @OneToOne(optional = true)
    @JoinColumns(value = {
            @JoinColumn(name="T090_091_INVESTOR_ID", referencedColumnName = "T284_INVESTOR_ID", nullable = false, insertable = false, updatable = false),
            @JoinColumn(name = "T090_102_ISSUER_ID", referencedColumnName = "T284_ISSUER_ID", nullable = false, insertable = false, updatable = false)
    })
    @NotFound(action = NotFoundAction.IGNORE)
    private InvestorIssuerEmailEntity investorIssuerEmail;

... 

InvestorIssuerEntityPK 
    @Id
    @Column(name = "T090_091_INVESTOR_ID", nullable = false, insertable = true, 
updatable = true, length = 18, precision = 0)
    private Long investorId;

    @Id
    @Column(name = "T090_102_ISSUER_ID", nullable = false, insertable = true, 
updatable = true, length = 18, precision = 0)
    private Long issuerId;

...

@IdClass(InvestorIssuerEmailEntityPK.class)
@Table(name = "T284_INVESTOR_ISSUER_EMAIL")
@Entity
InvestorIssuerEmailEntity
    @Column(name = "T284_INVESTOR_ID", nullable = false, insertable = true, 
updatable = true, length = 18, precision = 0)
    @Id
    private Long investorId;

    @Column(name = "T284_ISSUER_ID", nullable = false, insertable = true, 
updatable = true, length = 18, precision = 0)
    @Id
    private Long issuerId;

...

InvestorIssuerEmailEntityPK 

    @Column(name = "T284_INVESTOR_ID", nullable = false, insertable = true, 
updatable = true, length = 18, precision = 0)
    @Id
    private Long investorId;

    @Column(name = "T284_ISSUER_ID", nullable = false, insertable = true, 
updatable = true, length = 18, precision = 0)
    @Id
    private Long issuerId;  

我试图通过对两个实体使用与@EmbeddableId 相同的类,然后使用@AttributeOverrides 来解决类型不匹配问题,如下所示:

@Id
@EmbeddedId
@AttributeOverrides({
        @AttributeOverride(name = "investorId",
                column = @Column(name = "T284_INVESTOR_ID", nullable = false, insertable = true, updatable = true, length = 18, precision = 0)),
        @AttributeOverride(name = "issuerId",
                column = @Column(name = "T284_ISSUER_ID", nullable = false, insertable = true, updatable = true, length = 18, precision = 0))
})
private InvestorIssuerId investorIssuerId;

不过,我只对这两个实体进行了更改,仍然对其他实体使用 @IdClass 方法(是否仅对您的实体使用 @IdClass 或 @EmbeddableId,而不是两者?)

我们最终遇到了其他问题,例如“实体映射中的重复列”,因此我们恢复了这种方法,看看是否有其他解决方法。

有没有人有任何解决方案来解决这个问题?我查看了 StackOverflow,但没有遇到任何关联中使用的复合键具有不同名称的情况。

注意: 即使尝试了以下建议,我们仍然会收到此错误:org.hibernate.MappingException: Repeated column in mapping for entity: com.business.entity.InvestorIssuerEntity column: T090_091_INVESTOR_ID (应该使用 insert="false" update= 进行映射“错误的”)

我什至从 InvestorIssuerEntity 中删除了所有关联,但仍然遇到同样的问题。仅当我删除复合键类中的 @Column 注释时,该错误才消失。当然,查询不起作用,因为没有映射investorId!我不明白Hibernate 在哪里找到“映射中的重复列”,因为除了复合键之外,我已经删除了 T090_091_INVESTOR_ID 的所有提及。

我们在 InvestorIssuerEntity 中有其他关联,它们对相同的主键进行连接,但关联的实体在其复合键中也有额外的列。使用 @EmbeddedId 后,是否应该将它们用于所有实体?对于其他类,我们仍然使用 @IdClass。但是,这如何在任何地方导致“重复列”?

4

2 回答 2

5

看来我为您的情况找到了可行的解决方案:

@Entity
public class InvestorIssuerEntity {
    @EmbeddedId 
    private InvestorIssuerEntityPK investorIssuerEntityPK;

    @OneToOne(optional=true, mappedBy="investorIssuerEntity")
    private InvestorIssuerEmailEntity investorIssuerEmailEntity;
}

@Entity
public class InvestorIssuerEmailEntity {
    @EmbeddedId @AttributeOverrides({
        @AttributeOverride(name="investorId", column=@Column(name="T02_INV_ID")),
        @AttributeOverride(name="issuerId", column=@Column(name="T02_ISS_ID"))
    })
    private InvestorIssuerEntityPK investorIssuerEntityPK;

    @OneToOne(optional=true) @PrimaryKeyJoinColumns({
        @PrimaryKeyJoinColumn(name="T02_ISS_ID", referencedColumnName="T01_ISS_ID"), 
        @PrimaryKeyJoinColumn(name="T02_INV_ID", referencedColumnName="T01_INV_ID")
    })
    private InvestorIssuerEntity investorIssuerEntity;
}

@Embeddable
public class InvestorIssuerEntityPK implements Serializable {
    private static final long serialVersionUID = -1176248537673293674L;

    @Column(name="T01_INV_ID")
    private Long investorId;

    @Column(name="T01_ISS_ID")
    private Long issuerId;
}

它生成以下 DDL,这似乎是您正在寻找的:

create table InvestorIssuerEmailEntity (
    T02_INV_ID bigint not null,
    T02_ISS_ID bigint not null,
    primary key (T02_INV_ID, T02_ISS_ID)
)

create table InvestorIssuerEntity (
    T01_INV_ID bigint not null,
    T01_ISS_ID bigint not null,
    primary key (T01_INV_ID, T01_ISS_ID)
)

alter table InvestorIssuerEmailEntity 
    add constraint FKC2FBCC4E1E26612E 
    foreign key (T02_INV_ID, T02_ISS_ID) 
    references InvestorIssuerEntity
于 2011-01-07T14:27:23.757 回答
0

我想提一种替代方法:

  • pro:两个实体都可以使用自己的PK类
  • 缺点:1:1 关系体现在具有 1 个条目的 Set 中

您可以切换到 @OneToMany 关系并将相关实体存储在 Set 中。Set 将有 1 个条目,可以在后处理步骤中解包。

@OneToMany
@JoinColumns(value = {
        @JoinColumn(name="T090_091_INVESTOR_ID", referencedColumnName = "T284_INVESTOR_ID", nullable = false, insertable = false, updatable = false),
        @JoinColumn(name = "T090_102_ISSUER_ID", referencedColumnName = "T284_ISSUER_ID", nullable = false, insertable = false, updatable = false)
})
@NotFound(action = NotFoundAction.IGNORE)
private Set<InvestorIssuerEmailEntity> investorIssuerEmails;
于 2019-01-23T09:44:54.250 回答