复合键上的JPA实体连接列,日期为PK之一

时间:2017-08-21 17:47:42

标签: java mysql hibernate jpa

我必须使用JPA加入两个具有ManyToOne关系的表。

表1 - > MANF

@Entity
@Table(name = "manf")
public class ManF {

    @EmbeddedId
    private ManFCompositeKey manFCompositeKey;

    @Column(name = "name", length = 10)
    private String manFName;

    @Column(name = "desc", length = 150)
    private String manFDesc;
}

@Embeddable
public class ManFCompositeKey {

    @Column(name = "man_code", length = 20, nullable = false)
    private String manCode;

    @Column(name = "update_time", nullable = false)
    private Date updTime;
}

表2 - >产品

@Entity
@Table(name = "products")
public class Prod {

    @EmbeddedId
    private ProdCompositeKey prodCompositeKey;

    @Column(name = "name", length = 10)
    private String prodName;

    @Column(name = "prod_desc", length = 150)
    private String prodDesc;

    // -> JoinColumn here.
    @Column(name = "man_code", length = 20, nullable = false)
    private String manCode;
}

@Embeddable
public class ProdCompositeKey {

    @Column(name = "prod_code", length = 20, nullable = false)
    private String prodCode;

    @Column(name = "update_time", nullable = false)
    private Date updTime;
}

现在,manF(表1)可以有很多产品(表2)。因此,对于产品表中的每一行,可以有相同的manFCode。 我打算建立一个连接b / w T1和T2,使得产品中的manCode列表现为表1中引用man_code的表的FK。

以下是我写的连接条件:

  @ManyToOne(fetch = FetchType.LAZY, optional = false)
  @JoinColumns({
  @JoinColumn(name = "man_code", referencedColumnName = "man_code")
  })
  @Column(name = "man_code", length = 20, nullable = false)
  private ManF manF;

这应该是有道理的(我想),但是引发了一个错误,说明: ManF没有映射到单个属性。

现在我可以这样做:

  @ManyToOne(fetch = FetchType.LAZY, optional = false)
  @JoinColumns({
  @JoinColumn(name = "man_code", referencedColumnName = "man_code")
  @JoinColumn(name = "update_time", referencedColumnName = "update_time")
  })
  @Column(name = "man_code", length = 20, nullable = false)
  private ManF manF;

但是我会在插入ManF的时间上保留一个FK参考。

我需要知道如何在这里加入这两个表,以便我可以在ManF表的man_code和product(子)表中的man_code上创建一个FK引用。

2 个答案:

答案 0 :(得分:0)

您可以使用休眠native query并编写连接条件。如果这不是一个选项,我会特别将Manf上的embeddedId更改为常规id并在db中创建约束,以保持完整性并使用常规joincolumn条件。像这样:

SQL:ALTER TABLE'manf'添加UNIQUE'UNIQUE_CONSTRAINT'('man_code','update_time');

@Entity
@Table(name = "manf")
public class ManF {

    @Id
    @SequenceGenerator(name = "SEQUENCE_NAME", sequenceName = "SEQUENCE_NAME", allocationSize = 1, initialValue = 1)
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQUENCE_NAME")
    @Column(name = "man_code", length = 20, nullable = false)
    private String manCode;

    @Column(name = "update_time", nullable = false)
    private Date updTime;

    @Column(name = "name", length = 10)
    private String manFName;

    @Column(name = "desc", length = 150)
    private String manFDesc;
}

@Entity
@Table(name = "products")
public class Prod {

    @EmbeddedId
    private ProdCompositeKey prodCompositeKey;

    @Column(name = "name", length = 10)
    private String prodName;

    @Column(name = "prod_desc", length = 150)
    private String prodDesc;

    @ManyToOne(fetch = FetchType.LAZY, optional = false)
    @JoinColumn(name = "man_code")
    private ManF manF;
}

答案 1 :(得分:0)

这就是我所做的,实现这一目标。可能是一个黑客。

我已将表1中的man_code(ManF)放在主类中(它仍然是Embeddable)。但是在ManF课上我做了类似的事情:

@Entity
@Table(name = "manf")
public class ManF {

    @EmbeddedId
    private ManFCompositeKey manFCompositeKey;

    *@Column(name = "man_code", insertable = false, updatable= false)
    private String manCode;*

    @Column(name = "name", length = 10)
    private String manFName;

    @Column(name = "desc", length = 150)
    private String manFDesc;
}

@Embeddable
public class ManFCompositeKey {

    @Column(name = "man_code", length = 20, nullable = false)
    private String manCode;

    @Column(name = "update_time", nullable = false)
    private Date updTime;
}

另一方面,我更改了表2如下:

@Entity
@Table(name = "products")
public class Prod {

    @EmbeddedId
    private ProdCompositeKey prodCompositeKey;

    @Column(name = "name", length = 10)
    private String prodName;

    @Column(name = "prod_desc", length = 150)
    private String prodDesc;



    *@ManyToOne(fetch = FetchType.LAZY, optional = false)
    @JoinColumns({
    @JoinColumn(name = "man_code", referencedColumnName = 
    "man_code")})
    private ManF manF;*

    *@Column(name = "man_code", insertable = false, updatable = false)
    private String manCode;*

    @Column(name = "man_code", length = 20, nullable = false)
    private String manCode;
}

@Embeddable
public class ProdCompositeKey {

    @Column(name = "prod_code", length = 20, nullable = false)
    private String prodCode;

    @Column(name = "update_time", nullable = false)
    private Date updTime;
}

这在某种程度上有效,但我必须在Child表中添加一个新变量(此处:manCode,insertable和updatabale为false)

我不确定这是否是正确的做法。如果有人有更好和更优雅的想法来解决这个问题,请告诉我。