【问题标题】:Hibernate deletes data from DB without requesting for deletionHibernate 从数据库中删除数据而不请求删除
【发布时间】:2016-07-30 14:33:45
【问题描述】:

我有一个带有@ElementCollection 注释的实体Customer

@Entity
@Table(name = "customer")
public class Customer {
  @Id
  @Column(name = "id")
  @GeneratedValue(strategy= GenerationType.AUTO)
  private Long id;

  @ElementCollection
  @CollectionTable(name = "customer_alias", joinColumns = @JoinColumn(name = "customer_id") )
  @Column(name = "alias")
  private List<String> aliases;

}

当我启动我的应用程序时,表 customer_alias 包含几行。在我的代码中,我有一个迭代别名的循环:

for(String alias: customer.getAliases()) { ... }

奇怪的是,就在这一行之后,我在日志中看到了这两行:

Hibernate: select aliases0_.customer_id as cus1_3_0_, aliases0_.aliase as ali2_0_0_ from customer_alias aliases0_ where aliases0_.customer_id=?
Hibernate: delete from customer_alias where customer_id=?

当然 - 在“删除”行之后,数据会从数据库中删除,我不知道为什么。在我的代码中没有我调用 delete 的地方,它发生在 for 循环之后。看起来当我调用 getAliases() 时它会删除表。

【问题讨论】:

  • 你的 for 循环中有什么?
  • 可能跟这个有关:stackoverflow.com/questions/3742897/…
  • @Henry - 我只将这一行放在循环中 - System.out.println("Test"); 以确保它发生在循环中而不是循环内。仍然发生
  • @jonmartinsolaas - 感谢您的参考。我昨天访问了这个问题,但它似乎并不那么相关。就我而言,我不会在任何地方调用删除或插入。我也让我在别名表上有一个主键。
  • 您不必为此调用 delete 或 insert。关键是——当 Hibernate 对元素的身份感到困惑时,它会删除 ALL,然后从持有集合的实体中插入 ALL,当一个元素是脏的,或者可能是脏的,因为它不知道哪个单行在要更新的表。为了进一步混淆,这是实现的,以便在删除之前插入发生,除非您将巧妙的刷新语句放在合适的位置。如果没有,并且您在表上有一个唯一索引,您将违反约束。这可能是您的问题,也可能不是:o)

标签: java spring hibernate


【解决方案1】:

不幸的是,在阅读帖子和 cmets 的参考答案后,我找不到有效的解决方案。我通过创建一个实体Alias 解决了这个问题,该实体带有一个主键和@Id 字段。

将此答案留作参考,不接受它,希望将来有更好的解决方案。

【讨论】:

    【解决方案2】:

    来自https://en.wikibooks.org/wiki/Java_Persistence/ElementCollection

    JPA 2.0 规范没有提供定义 Id 的方法 可嵌入的。但是,要删除或更新 ElementCollection 映射,通常需要一些唯一键。 否则,在每次更新时,JPA 提供者都需要删除 实体的 CollectionTable 中的所有内容,然后插入 值回来了。因此,JPA 提供者很可能会假设 Embeddable 中所有字段的组合都是唯一的,在 与外键 (JoinColumn(s)) 组合。然而这可以 效率低下,或者如果 Embeddable 很大则不可行,或者 复杂。

    一些 JPA 提供者可能允许在 嵌入式,解决这个问题。请注意,在这种情况下,ID 只需要 对于集合而不是表来说是唯一的,因为外键是 包括。有些可能还允许 CollectionTable 上的唯一选项 用于此。否则,如果您的 Embeddable 很复杂,您可以 考虑将其设为实体并改用 OneToMany。

    【讨论】:

    • 是的,在cmets中有引用,我自己也找到了。它不能解决问题,或者至少我不明白为了解决问题我应该改变什么。它只是解释了其背后的原因,不幸的是,本段或其他答案都没有给出可行的解决方案:/
    • 我理解,理论上,除非您像 OneToMany 那样有一些表映射,否则您无法阻止删除表中的条目。可以使用 OneToMany 或通过编写 Entity 类方法以公开与 ElementCollection 相同的 API 来将 OneToMany 实现为 ElementCollection。我希望我清楚第二选择
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-24
    • 2017-12-05
    • 2022-01-07
    相关资源
    最近更新 更多