【问题标题】:There should be one non-read-only mapping defined for the primary key field应该为主键字段定义一个非只读映射
【发布时间】:2015-06-03 02:36:23
【问题描述】:

您好,我有以下代码(使用 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<...>,因为还有几个其他类类似于 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 表。

【问题讨论】:

  • 很难判断出了什么问题。您可以尝试删除映射中的泛型,看看这是否会以某种方式混淆问题
  • @Chris 我删除了泛型但同样的错误。查看我编辑的帖子。

标签: jpa mapping eclipselink


【解决方案1】:

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

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

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

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

@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 中删除了嵌入的 HeaderPk 并添加了各个字段。其余代码与原始帖子中的相同。 EclipseLink 不再抱怨了。

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

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

编辑:我忘了提及...在 RecordPk 中您需要删除 @MapsId("headerPk"),因为 headerPk 不再嵌入到 RecordPk 中。

【讨论】:

    猜你喜欢
    • 2019-10-04
    • 1970-01-01
    • 2021-02-13
    • 1970-01-01
    • 1970-01-01
    • 2011-04-21
    • 1970-01-01
    • 2014-10-28
    • 2014-03-07
    相关资源
    最近更新 更多