【问题标题】:Java: Repeated column in mapping for collectionJava:集合映射中的重复列
【发布时间】:2021-12-12 23:03:39
【问题描述】:

我正在尝试使用 LinkedHashMap 为我的主要实体 B 创建一个 OneToMany 映射,其中包含实体 VCP,但我收到以下错误:

集合映射中的重复列: com.test.model.B.pricing 列:b_name

我可能是错的,但我相信它与@JoinColumns@MapKeyJoinColumn 注释有关,因为我以前没有做过这样的事情,所以我很确定我做这部分不正确.

我的目标是我应该能够提供三个字段:

b_name pcc_id 例如VC/VCId

为了得到ad_a 例如P.

另外,如果有更好的方法来构建事物,那么我会全神贯注,因为我个人不太喜欢我设置表格的方式(如果我能有 bb_p 表,其中b_p 可以只包含来自p 映射的所有五个字段(键和值)。

这是我的主要实体

@Setter
@Getter
@Entity
@Table(name = "b")
public class B implements Serializable {

  @Id
  @Column(nullable = false)
  private String name;

  @OneToMany(cascade = CascadeType.PERSIST)
  @JoinTable(
          name = "b_p",
          joinColumns = @JoinColumn(name = "b_name", referencedColumnName = "name"))
  @MapKeyJoinColumns({
          @MapKeyJoinColumn(name = "b_name"),
          @MapKeyJoinColumn(name = "p_c"),
          @MapKeyJoinColumn(name = "c_id")
  })
  private Map<VC, Price> pricing = new LinkedHashMap<>();

  ...
}

地图的钥匙

@Setter
@Getter
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Table(name = "v_c")
public class VC implements Serializable {

  @EmbeddedId private VCId vcId;
}

密钥的 PK/复合密钥

@Setter
@Getter
@NoArgsConstructor
@AllArgsConstructor
@Embeddable
public class VCId implements Serializable {

  @Column(name = "b_name")
  private String bName;

  @Column(name = "p_c")
  private SomeEnum pc;

  @Column(name = "c_id")
  private String cId;
}

地图的价值

@Setter
@Getter
@NoArgsConstructor
@Embeddable
@Entity
@Table(name = "price")
public class Price implements Serializable {

  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  @Column(name = "id")
  private long id;

  @Column(name = "amount")
  private BigDecimal amount;

  @Column(name = "discount_amount")
  private BigDecimal discountAmount;
}

数据库表

CREATE TABLE b
(
    name                    VARCHAR(100) NOT NULL PRIMARY KEY
    ...
);

CREATE TABLE v_c
(
    bundle_name         VARCHAR(100) NOT NULL,
    physical_currency   TEXT         NOT NULL,
    coin_id             VARCHAR(50)  NOT NULL,

    FOREIGN KEY (b_name) REFERENCES b (name) ON DELETE CASCADE,
    PRIMARY KEY (b_name, p_c, c_id)
);

CREATE TABLE p
(
    id                  BIGSERIAL    NOT NULL PRIMARY KEY,
    amount              NUMERIC,
    discount_amount     NUMERIC      DEFAULT 0.00
);

CREATE TABLE b_p
(
    bname         VARCHAR(100) NOT NULL,
    p_c   TEXT    NOT NULL,
    c_id          VARCHAR(50)  NOT NULL,
    price_id      BIGSERIAL    NOT NULL,

    FOREIGN KEY (b_name, p_c, c_id) REFERENCES v_c (b_name, p_c, c_id) ON DELETE CASCADE,
    FOREIGN KEY (price_id) REFERENCES price (id) ON DELETE CASCADE,
    PRIMARY KEY (b_name, p_c, c_id)
);

【问题讨论】:

  • 让 bundle_name 成为 VirtualCurrency 的一部分似乎违反直觉。您不希望您的虚拟货币可用于多个捆绑包吗?
  • @Lookslikeitsnot well 我拥有 bundle_name 的唯一原因只是因为我想确保获得特定捆绑包的正确 VirtualCurrency。从理论上讲,另一个捆绑包可以具有相同的 VirtualCurrency 是完全没问题的,并且 100% 可能,实际上这是预期的,但最终每个捆绑包的定价可能不同。如果我可以在不使用 bundle_name 作为复合键的一部分的情况下实现这一点,那么我 100% 会。
  • 这不是通过在 b_p 中设置 b_name 和 b_name, p_c, c_id 作为该表的 PK 来实现的吗?将FOREIGN KEY (b_name) REFERENCES b (name) ON DELETE CASCADE 添加到 b_p,您可以从 v_c 中删除 b_name。
  • @Lookslikeitsnot Awesome,非常感谢,伙计!

标签: java spring postgresql jpa


【解决方案1】:

为防止重复映射错误,您只需指定哪个连接应该更新列,如下所示:

@OneToMany(cascade = CascadeType.PERSIST)
@JoinTable(name = "bundle_pricing",
  joinColumns = @JoinColumn(name = "bundle_name",
    referencedColumnName = "name"))
@MapKeyJoinColumns({
  @MapKeyJoinColumn(name = "bundle_name", insertable = false, updatable = false),
  @MapKeyJoinColumn(name = "physical_currency"), @MapKeyJoinColumn(name = "coin_id")})
private Map<VirtualCurrency, Price> pricing = new LinkedHashMap<>();

注意 insertable = false, updatable = false 用于 MapKeyJoinColumn 中的 bundle_name

【讨论】:

    【解决方案2】:

    从 MapKeyJoinColumns 中删除 @MapKeyJoinColumn(name = "bundle_name"),因为当我们在 JoinTable 中创建 JoinColumn 时,它将创建我们不需要再次提及的列。

    @JoinTable(
              name = "bundle_pricing",
              joinColumns = @JoinColumn(name = "bundle_name", referencedColumnName = "name"))
      @MapKeyJoinColumns({
              @MapKeyJoinColumn(name = "physical_currency"),
              @MapKeyJoinColumn(name = "coin_id")
      })
    

    【讨论】:

    • 谢谢,这摆脱了那个错误,但现在它给出了这个:A Foreign key refering com.test..base.model.VirtualCurrency from com.test.base.model.Bundle has the wrong number的列。应该是 3
    猜你喜欢
    • 1970-01-01
    • 2013-10-07
    • 1970-01-01
    • 2012-02-08
    • 2014-01-10
    • 2018-03-30
    • 1970-01-01
    • 2013-11-12
    • 1970-01-01
    相关资源
    最近更新 更多