【问题标题】:Update Entity Relationship via UPDATE .. SET Query通过 UPDATE .. SET 查询更新实体关系
【发布时间】:2018-02-08 18:10:19
【问题描述】:

我有两个实体:

class A {
@OneToMany(mappedBy = "a")
List<B> bs;
// getter/ setter
}
class B {
@ManyToOne
A a;
// getter/ setter
}

要删除一个 b,我首先需要使该关系无效。 “传统上”我会这样做:

A a = em.getReference(A.class, entityIdA)
B b = em.getReference(B.class, entityIdB);
a.getBs().remove(b);
b.setA(null);
em.remove(b);

如果a 的列表越来越大(在我的例子中是几百个),这不是很高效。

我知道我也可以使用 JPQL 创建更新查询。

类似这样的:

Query q = em.createQuery("UPDATE B b SET b.a = NULL");
q.executeUpdate();

问题:abs 列表中删除一个 b 对应的JPQL 查询是什么?

简而言之: 如何翻译

a.getBs().remove(b);

进入 JPQL 查询?

编辑:提到的更新查询转换为

UPDATE B SET A_ID = ? WHERE (ID = ?)
    bind => [null, 2]

表格如下所示:

A
ID

B
ID    A_ID

【问题讨论】:

  • 一个A 在数据库中没有Bs 的列表;正如您所做的那样,这只是您需要取消的 FK。然后你需要做的是从缓存中清除任何A对象,和/或在A上调用em.refresh(),所以A被重新加载(没有其他B)跨度>
  • 我明白了。但是a 仍然有一个连接表,其中包含已删除b 的键。如果我只执行我发布的查询,a 仍将拥有已删除的b 的 FK。
  • 如果您使用的是连接表而不是外键,那么您提到的 JPQL 更新了什么?没有FK意味着更新B边时必须更新连接表
  • 我已经“建议”您在执行 JPQL 时查看调用的 SQL。然后你把它放在问题中。然后它会告诉你该 JPQL 发生了什么,这样你就可以理解为什么会得到这个结果
  • 如前所述...如果您已映射 1-N 双向关系,则存在 JOIN TABLE 或外键。你仍然有两个所以没有,这是完全错误的

标签: java jpa eclipselink derby jpql


【解决方案1】:

从 cmets 和 this 的问题来看,改变关系的拥有方就足够了。

因此,要做

a.getBs().remove(b);

作为 jpql 查询,可以做到

"UPDATE B b SET b.a = NULL"

这将释放ab之间的双向关系。

请注意,您可能需要清除 L2 缓存或关闭 EntityManagerFactory 才能使其生效。

factory.getCache().evictAll();

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-08-17
    • 2023-03-24
    • 2021-07-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-23
    • 1970-01-01
    相关资源
    最近更新 更多