【问题标题】:JPA Join Tables with two fields, one of them a primary key具有两个字段的 JPA 连接表,其中一个是主键
【发布时间】:2022-08-20 09:15:25
【问题描述】:

问题是当@ManyToOne 创建一个@Joincolumn ID_REPORT (它是一个主键)和@Joincolumn ID_TEMPLATE_DEFAULT

实体映射中的重复列:CurReport 列:id_report(应使用 insert=\"false\" update=\"false\" 映射)

代码

第一个表 CUR_TEMPLATE

CREATE TABLE CUR_TEMPLATE 
   (    
    ID_REPORT NUMBER(5,0) NOT NULL, 
    ID_TEMPLATE NUMBER(5,0) NOT NULL, 
    -- Other fields
   );
 
ALTER TABLE CUR_TEMPLATE ADD CONSTRAINT PK_CUR_TEMPLATE PRIMARY KEY (ID_REPORT, ID_TEMPLATE)

-- CUR_TEMPLATE foreign keys
ALTER TABLE CUR_TEMPLATE ADD CONSTRAINT FK_CUR_PLAN_REFERENCE_CUR_REPO FOREIGN KEY (ID_REPORT)
      REFERENCES CUR_REPORTS (ID_REPORT);

第二个表 CUR_REPORTS


-- CUR_REPORTS definition
CREATE TABLE CUR_REPORTS 
   (    
    ID_REPORT NUMBER(3,0) NOT NULL, 
    NAME_REPORT VARCHAR2(100) NOT NULL, 
    -- other fields 
    ID_TEMPLATE_DEFAULT NUMBER(5,0), 
    -- other fields
   ) ;

ALTER TABLE CUR_REPORTS ADD CONSTRAINT PK_CUR_REPORTS PRIMARY KEY (ID_REPORT)

ALTER TABLE CUR_REPORTS CONSTRAINT FK_CUR_REPO_REFERENCE_CUR_PLAN FOREIGN KEY (ID_REPORT, ID_TEMPLATE_DEFAULT)
      REFERENCES CUR_TEMPLATE (ID_REPORT, ID_TEMPLATE) 

第一个表 CUR_REPORTS 实体 CurReport


@Entity
@Table(name = \"CUR_REPORTS\")
@IdClass(CurPlantillaPK.class)
@Getter
@Setter
public class CurReport {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = \"ID_REPORT\", nullable = false)
    private Long id;

    @Column(name = \"NAME_REPORT\", nullable = false, length = 100)
    private String nombreReporte;

    @ManyToOne(fetch = FetchType.LAZY) <---WHERE IS THE PROBLEM 
    @JoinColumn(name = \"ID_REPORT\", referencedColumnName = \"ID_REPORTE\")
    @JoinColumn(name = \"ID_TEMPLATE_DEFAULT\", referencedColumnName = \"ID_TEMPLATE\")
    private CurTemplate curTemplate;

    @OneToMany(mappedBy = \"curReport\")
    private Set<CurTemplate> curTemplates= new LinkedHashSet<>();
}

第二个表 CUR_TEMPLATE 实体 CurReport


@Entity
@Table(name = \"CUR_TEMPLATE\")
@IdClass(CurPlantillaPK.class)
@Getter
@Setter
public class CurTemplate {
    
    @Id
    @Column(name = \"ID_REPORT\", nullable = false)
    private Long idReport;

    @Id
    @Column(name = \"ID_TEMPLATE\", nullable = false)
    private Long idTemplate;

    
    @ManyToOne(optional = false, fetch = FetchType.LAZY)
    @JoinColumn(name = \"ID_REPORT\", foreignKey = @ForeignKey(name = \"FK_CUR_PLAN_REFERENCE_CUR_REPO\"), referencedColumnName = \"ID_REPORT\", insertable = false, updatable = false)
    private CurReport curReport;

}

当我添加可插入=假时,可更新=假

@JoinColumn(name = \"ID_REPORT\",referencedColumnName = \"ID_REPORT\",可插入=false,可更新=false)

不允许在属性中混合可插入和不可插入的列:CurTemplate

我如何映射这些关系? 当 FK 的一个字段是列 PK 时如何解决@JoinColumn?

  • 您应该将 @JoinColumns 与多个连接列一起使用
  • 是的,其中一个必须是@id,但我可以从其他表中引用 fk,我所做的是用这些表的 pk 的类型复制列 \"ID_TEMPLATE_DEFAULT\",并将 insertale 和 updatable 设置为 false ,但我认为有更好的解决方案

标签: java hibernate jpa java-ee-8 jpa-annotations


【解决方案1】:

您可以使用派生的身份和映射CurTemplate,如下所示:

@Entity
@Table(name = "CUR_TEMPLATE")
@IdClass(CurTemplatePK.class)
@Getter
@Setter
public class CurTemplate {

    @Id
    @Column(name = "ID_TEMPLATE", nullable = false)
    private Long idTemplate;

    @Id
    @ManyToOne(optional = false, fetch = FetchType.LAZY)
    @JoinColumn(name = "ID_REPORT", foreignKey = @ForeignKey(name = "FK_CUR_PLAN_REFERENCE_CUR_REPO"), referencedColumnName = "ID_REPORT", insertable = false, updatable = false)
    private CurReport curReport;

}

然后你需要一个@IdClass,像这样:

public class CurTemplatePK {
    Long idTemplate; // matches name of @Id attribute
    Long curReport; // matches name of @Id attribute and type of CurReport PK
}

然后,您应该为默认模板键使用基本映射,并为默认模板对象提供一个 getter:

@Entity
@Table(name = "CUR_REPORTS")
@IdClass(CurPlantillaPK.class)
@Getter
@Setter
public class CurReport {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "ID_REPORT", nullable = false)
    private Long id;

    @Column(name = "NAME_REPORT", nullable = false, length = 100)
    private String nombreReporte;

    @Column(name = "ID_TEMPLATE_DEFAULT")
    private Long idDefaultTemplate;

    @OneToMany(mappedBy = "curReport")
    private Set<CurTemplate> curTemplates= new LinkedHashSet<>();

    public CurTemplate getDefaultTemplate() {
        return this.curTemplates.stream()
                .filter(template -> template.getIdTemplate().equals(idDefaultTemplate))
                .findFirst()
                .orElse(null);
    {
}

如果您想允许客户端设置默认模板,您需要实现一个 setter,首先验证新的默认模板是否已经在集合 curTemplates 中。

【讨论】:

    猜你喜欢
    • 2013-01-21
    • 1970-01-01
    • 2015-02-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-16
    • 2015-12-13
    相关资源
    最近更新 更多