JPA OneToOne关联,其中2个实体使用复合主键但使用不同的列名称? [英] JPA OneToOne association where 2 entities use composite primary keys but use different column names?

查看:122
本文介绍了JPA OneToOne关联,其中2个实体使用复合主键但使用不同的列名称?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们试图将Hibernate与一个使用组合键的 的数据库结合使用,这已经给我们带来了很多麻烦。
不幸的是,我们不能改变模式,所以我们必须在我们的领域之间做很多额外的映射。我们仅限于使用JPA 1.0和Hibernate 3.3。

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

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

 由org.hibernate引发。 TypeMismatchException为类com.business.entity.InvestorIssuerEmailEntity提供了错误类型的标识。 
预期:类com.business.entity.InvestorIssuerEmailEntityPK,获得类com.business.entity.InvestorIssuerEntityPK;

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

pre $ I $ C $ @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
私人长期issuerId;

(其他字段省略)

@OneToOne(可选= 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)
私人长期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
私人长期issuerId;

...

InvestorIssuerEmailEntityPK

@Column(name =T284_INVESTOR_ID,nullable = false,insertable = true,
可更新= 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
私人长期issuerId;

我试图通过使用与@EmbeddableId相同的类来解决Type Mismatch问题这两个实体,然后使用@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 ))
})
私人InvestorIssuerId investorIssuerId;

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



我们最终得到了其他问题,如实体映射中的重复列,所以我们已经恢复到这种方式,看看是否有其他解决方法。



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



注意:
甚至在尝试下面的建议之后,我们仍然得到这个错误:org.hibernate.MappingException:实体映射中的重复列:com.business.entity.InvestorIssuerEntity列:T090_091_INVESTOR_ID(应该映射为insert =false更新=false)



我甚至删除了来自InvestorIssuerEntity的所有关联,并且仍然存在同样的问题。当我删除组合键类中的@Column注释时,该错误就消失了。当然,查询不起作用,因为investorId没有被映射!我不明白Hibernate在哪里找到映射中的重复列,因为除了复合键以外,我已经删除了T090_091_INVESTOR_ID的所有提及。



我们在InvestorIssuerEntity中有其他关联,它们在相同的主键上进行连接,但关联的实体在其复合键中也有其他列。一旦你使用@EmbeddedId,你是否应该将它们用于所有实体?我们仍然使用@IdClass作为其他类。但是,那么如何在任何地方造成重复的专栏呢?

解决方案

看起来我已经为您的案例找到了一个可行的解决方案:

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

@OneToOne(可选= true,mappedBy =investorIssuerEntity)
私人InvestorIssuerEmail实体investorIssuerEmailEntity;


实体
公共类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(可选= true)@PrimaryKeyJoinColumns({
@PrimaryKeyJoinColumn(name =T02_ISS_ID,referencedColumnName =T01_ISS_ID),
@PrimaryKeyJoinColumn(name =T02_INV_ID ,referencedColumnName =T01_INV_ID)
})
私人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,
主键(T02_INV_ID,T02_ISS_ID)


创建表InvestorIssuerEntity(
T01_INV_ID bigint不为空,
T01_ISS_ID bigint不为null,
主键(T01_INV_ID ,T01_ISS_ID)


alter table InvestorIssuerEmailEntity
添加约束FKC2FBCC4E1E26612E
外键(T02_INV_ID,T02_ISS_ID)
引用InvestorIssuerEntity


We are trying to use Hibernate with a database that uses a lot of composite keys and it's been causing us a lot of headaches. Unfortunately, we can't change the schema so we have to do a lot of additional mapping betwen our fields. We are restricted to using JPA 1.0 and Hibernate 3.3.

The biggest problem we've had so far is to do with a one-to-one association between two entities using a composite key of 2 values, where the tables have different names for these columns (the DB has a naming convention of having a table-specific prefix on each column.)

Whenever we perform our query, we get this exception:

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; 

The two classes for these tables, InvestorIssuerEntity and InvestorIssuerEmailEntity, have an optional @OneToOne assocation (in some cases InvestorIssuer has no matching record in 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;  

I've tried to get around the Type Mismatch problem by using the same class as the @EmbeddableId for the two entities, and then using @AttributeOverrides, like this:

@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;

I only did the change for these two entities though, still using the @IdClass approach for the other entities (Is it a case of only using @IdClass OR @EmbeddableId for your entities, not both?)

We ended up getting other issues like "Repeated column in mapping for entity", so we've reverted to this approach to see if there's other workarounds to this.

Does anyone have any solutions to get around this problem? I've looked around StackOverflow but haven't come across any cases where the composite keys used in the association have different names.

Note: Even after trying the suggestion below, we still get this error: org.hibernate.MappingException: Repeated column in mapping for entity: com.business.entity.InvestorIssuerEntity column: T090_091_INVESTOR_ID (should be mapped with insert="false" update="false")

I even removed ALL associations from InvestorIssuerEntity and still got the same problem. The error only went away when I removed the @Column annotation in the composite key class. Of course, the queries didn't work because the investorId wasn't mapped! I don't understand where Hibernate was finding the "Repeated column in mapping", since I'd already removed every mention of T090_091_INVESTOR_ID else except for the composite key.

We have other associations in InvestorIssuerEntity that do a join on the same primary keys, but the associated entities also have additional columns in their composite keys. Once you use @EmbeddedId, are you supposed to use them for all entities? We still use @IdClass for the others classes. But then how does that cause a "repeated column" anywhere?

解决方案

It seems I got a working solution for your case:

@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;
}

It generates the following DDL, which seems to be what you are looking for:

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

这篇关于JPA OneToOne关联,其中2个实体使用复合主键但使用不同的列名称?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆