【问题标题】:JPA persists already persisted Objects from a ManyToMany relationshipJPA 持久化来自多对多关系的已持久化对象
【发布时间】:2011-11-28 22:21:36
【问题描述】:

我在 A 类和 B 类之间有一个 @ManyToMany 关系:A 类引用 B 类实例的集合,并且这种关系被配置为 CascadeType.ALL。所以当 A 被实体管理器持久化时,A 引用的 B 实例也被持久化。

A 和 B 都有一个使用 GenerationType.IDENTITY 策略声明的 ID,以使用 MySQL 数据库中的 auto_inc。

问题是:

  1. 我新建了一个A
  2. 我使用 JPQL 从 entityManager 加载了一些现有的 B 对象
  3. 我将 B 对象添加到 A 的 B 集合中

=> JPA 尝试持久化 B 对象,尽管它们已经被持久化(它们刚刚被加载)。

我不明白为什么它会再次尝试持久化它们,它们已正确加载,并且它们的自动生成的 id 也已加载好。

ManyToMany 声明:

@ManyToMany(cascade={CascadeType.ALL})
@JoinTable(name = "ENTRY_ENTITIES", joinColumns =
@JoinColumn(name = "ENTRY", referencedColumnName = "ID"),
inverseJoinColumns = @JoinColumn(name = "ENTITY", referencedColumnName = "ID"))
private List<Entity> entities;

从数据库加载现有对象的查询:

T result = (T) entityManager.createQuery("SELECT x FROM " + entityName + " x WHERE x.externalId='" + externalId + "'").getSingleResult();

坚持:

UserTransaction transaction = getTransaction();
try {
    transaction.begin();
    entityManager.persist(entity);
    transaction.commit();
} catch (Throwable t) {
    Logger.getLogger(JpaDao.class.getName()).log(Level.SEVERE, null, t);
}

非常感谢您的帮助!

【问题讨论】:

  • 向我们展示实体的代码、它们的映射以及执行持久化的代码。告诉我们您正在使用哪个 JPA 引擎。请注意,在 ManyToMany 上级联 ALL 是错误的:您不希望在删除 A 时删除 A 的所有 B,因为 B 被其他 As 引用。
  • 好的,感谢您的帮助。我添加了代码。

标签: java jpa jpql


【解决方案1】:

我不确定这是否是您的问题的原因,但您应该将整个事情包含在事务中。不仅仅是持久性部分:

start transaction
load B from DB
create new A
add B to A
commit transaction

正如我在 cmets 中所说,您还有其他设计和编码问题:

  • CascadeType.ALL 在 ManyToXxx 关联上是错误的。您不希望在删除 A 时删除 A 的所有 B,因为这些 B 被其他 As 引用。这将导致违反约束(在最好的情况下)或不一致的数据库(在最坏的情况下,如果您没有定义约束)
  • 不要在查询中使用字符串连接。使用参数化查询。这将避免引用问题和注入攻击:SELECT x FROM A x WHERE x.externalId = :externalId

【讨论】:

  • 谢谢,不幸的是我不能将加载和持久化放在同一个事务中,因为首先我加载 B,然后将它们显示在 JSF 页面上,然后当用户提交表单时,我创建一个 A 并坚持它。所以它不在同一个http请求中。还是我要再次加载它们?
  • 不,您不必重新加载它们。您使用的是哪个 JPA 引擎?关联是双向的吗?向我们展示这两个实体的完整代码以及用于关联它们的代码。
【解决方案2】:

在您将 B 实体添加到 A 的时间点,这些 B 实体可能是另一个持久性上下文的一部分。您是否尝试在开始事务之后、之前在 B 实体上使用 merge operation > 将它们添加到您的 A 实体中。

【讨论】:

    猜你喜欢
    • 2023-03-20
    • 2017-10-10
    • 1970-01-01
    • 2017-01-10
    • 2012-12-17
    • 2011-12-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多