应该为主键字段

时间:2015-06-01 13:13:54

标签: jpa mapping eclipselink

您好我有以下代码(使用eclipselink 2.6):

变速箱:

@Entity    
public class Transmission {     

    @Column(name="TRANSMISSION_ID")
    @Id private Long id;

    @Column(name="TRANSMISSION_CONTENT")
    private String content;
....
}

HeaderPk:

@Embeddable
public class HeaderPk {

    // this is a foreign key to "TRANSMISSION_ID" in Transmission
    @Column(name="FK_TRANSMISSION_ID")
    private Long transmissionId;

    @Column(name="MAILBOX_ID")
    private String mailboxId;

    @Column(name="TRANSMISSION_TIME")
    private Time transmissionTime;
    ...
}

标题

@MappedSuperclass
public abstract class Header {

    @EmbeddedId
    private HeaderPk id = new HeaderPk();

    @MapsId("transmissionId")
    @ManyToOne(fetch=FetchType.EAGER) 
    @JoinColumn(name="FK_TRANSMISSION_ID", referencedColumnName="TRANSMISSION_ID")
    private Transmission transmission;        
    ....
}

VoucherHeader:

@Entity
public class VoucherHeader extends Header {
    // a bunch of additional fields
    ....
    ....    
}

RecordPk:

@Embeddable
public class RecordPk {

    @Column(name="RECORD_NUMBER")
    private Integer recordNumber;

    @Embedded   
    private HeaderPk headerPk;
    ...
    ...
}

记录:

@MappedSuperclass
public abstract class Record<T> {

    @EmbeddedId
    private RecordPk id;

    @MapsId("headerPk")
    @ManyToOne
    @JoinColumns({
        @JoinColumn(name="FK_TRANSMISSION_ID", referencedColumnName="FK_TRANSMISSION_ID"),
        @JoinColumn(name="FK_MAILBOX_ID", referencedColumnName="MAILBOX_ID"),
        @JoinColumn(name="FK_TRANSMISSION_TIME", referencedColumnName="TRANSMISSION_TIME")
    })
    private T header;
    ....
    ....
}

VoucherRecordTypeA:

@Entity
public class VoucherRecordTypeA extends Record<VoucherHeader> {
    // a bunch of additional column-mapped fields
    ...
}

尝试运行程序时出现以下错误: 应该为主键字段[VoucherRecordTypeA.MAILBOX_ID]定义一个非只读映射...我知道它抱怨有多个可写映射字段,但我无法弄清楚如何解决这个问题。

如果我将 VoucherRecordTypeA 修改为此错误,该错误就会消失...

@Entity
public class VoucherRecordTypeA  {
    @EmbeddedId
    private RecordPk id;

    @MapsId("headerPk")
    @ManyToOne
        @JoinColumns({
            @JoinColumn(name="FK_TRANSMISSION_ID", referencedColumnName="FK_TRANSMISSION_ID"),
            @JoinColumn(name="FK_MAILBOX_ID", referencedColumnName="MAILBOX_ID"),
            @JoinColumn(name="FK_TRANSMISSION_TIME", referencedColumnName="TRANSMISSION_TIME")
    })
    private VoucherHeader header;

    // a bunch of additional column-mapped fields
    ...
}

但理想的解决方案是让VoucherRecordTypeA扩展Record&lt; ...&gt;因为有几个类似于VoucherRecordTypeA的其他类。任何帮助将不胜感激。

修改 试过以下

@MappedSuperclass
public abstract class Record {              
    @EmbeddedId
    private RecordPk id;

    @MapsId("headerPk")
    @ManyToOne
    @JoinColumns({
        @JoinColumn(name="FK_TRANSMISSION_ID", referencedColumnName="FK_TRANSMISSION_ID"),
        @JoinColumn(name="FK_MAILBOX_ID", referencedColumnName="MAILBOX_ID"),
        @JoinColumn(name="FK_TRANSMISSION_TIME", referencedColumnName="TRANSMISSION_TIME")
    })
    private VoucherHeader header;
    ....
    ....
}

同样的错误。我注意到它正在抱怨应该为[VoucherRecordTypeA。 MAILBOX_ID ]定义非只读映射...表VoucherRecordTypeA的列FK_MAILBOX_ID不是MAILBOX_ID ... MAILBOX_ID是引用的列VoucherHeader表。

1 个答案:

答案 0 :(得分:1)

如果列的名称和@JoinColumn中引用的列相同,EclipseLink似乎不会抱怨。所以这没有错误:

@Embeddable
public class RecordPk {

@Column(name="RECORD_NUMBER")
private Integer recordNumber;

@Column(name="FK_TRANSMISSION_ID", insertable=false, updatable=false)
private Long transmissionId;

@Column(name="FK_MAILBOX_ID", insertable=false, updatable=false)
private String mailboxId;

@Column(name="FK_TRANSMISSION_TIME", insertable=false, updatable=false)
private Time transmissionTime;
...
...
}

但是这是不可接受的,因为实际的列名称与引用的列名称不同。就像我在原帖中所述,如果我将RecordPk和关系映射到VoucherRecordTypeA并在@JoinColumn注释中使用正确的列名称,这不是问题。我继续尝试了这个解决方案,它没有给我任何错误。

<key>date-sent</key>    
<integer>1264001747</integer>

所以基本上我从RecordPk中删除了嵌入式HeaderPk并添加了各个字段。其余代码与原始帖子中的相同。 EclipseLink不再抱怨了。

这是我的分析:此问题仅发生在使用 @MappedSuperclass 注释的类上。只要列名和引用的列名相同,就可以在@MappedSuperclass中使用带有嵌套id的派生EmbeddedId以及关系上的@JoinColumn。如果他们不一样,它就会破裂。但是,如果在使用@Entity注释的类上进行相同的设置,则不会发生这种情况。遵循帖子中的代码可能会更好地理解。

我的分析是否正确?这是一个错误吗?

编辑:我忘记提及...在记录中你需要删除 @MapsId(“headerPk”),因为headerPk不再嵌入到RecordPk中。< / p>