Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/jpa/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java JPA持久化来自多个关系的已持久化对象_Java_Jpa_Jpql - Fatal编程技术网

Java JPA持久化来自多个关系的已持久化对象

Java JPA持久化来自多个关系的已持久化对象,java,jpa,jpql,Java,Jpa,Jpql,我在类a和类B之间有一个@ManyToMany关系:类a引用了类B实例的集合,这个关系被配置为CascadeType.ALL。因此,当使用实体管理器持久化a时,a引用的B实例也会持久化 A和B都使用GenerationType.IDENTITY策略声明了一个ID,以使用MySQL数据库中的auto_inc 问题是: 我创建了一个新的 我使用JPQL从entityManager加载一些现有的B对象 我将B对象添加到A的B集合中 =>JPA尝试持久化B对象,尽管它们已经被持久化(它们刚刚被加载) 我

我在类a和类B之间有一个@ManyToMany关系:类a引用了类B实例的集合,这个关系被配置为CascadeType.ALL。因此,当使用实体管理器持久化a时,a引用的B实例也会持久化

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

问题是:

  • 我创建了一个新的
  • 我使用JPQL从entityManager加载一些现有的B对象
  • 我将B对象添加到A的B集合中
  • =>JPA尝试持久化B对象,尽管它们已经被持久化(它们刚刚被加载)

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

    许多宣言:

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

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

    非常感谢你的帮助

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

    start transaction
    load B from DB
    create new A
    add B to A
    commit transaction
    
    正如我在评论中所说,您还有其他设计和编码问题:

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

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

    start transaction
    load B from DB
    create new A
    add B to A
    commit transaction
    
    正如我在评论中所说,您还有其他设计和编码问题:

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

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

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

    显示实体的代码,它们的映射,以及执行持久性的代码。告诉我们您正在使用的JPA引擎。请注意,CacsCode ALL on a ManyToMany是错误的:删除a时,您不希望删除a的所有B,因为B被其他As引用。好的,谢谢您的帮助。我添加了代码。向我们展示实体的代码、它们的映射以及执行持久化的代码。告诉我们您正在使用的JPA引擎。请注意,CacsCode ALL on a ManyToMany是错误的:删除a时,您不希望删除a的所有B,因为B被其他As引用。好的,谢谢您的帮助。我添加了代码。谢谢,不幸的是,我不能将加载和持久化放在同一个事务中,因为首先我加载Bs,然后在JSF页面上显示它们,然后当用户提交表单时,我创建一个a并持久化它。所以它不在同一个http请求中。或者我应该再装一次吗?不,你不应该再装一次。您使用的是哪个JPA引擎?这种联系是双向的吗?向我们展示这两个实体的完整代码以及用于关联它们的代码。谢谢,不幸的是,我不能将加载和持久化放在同一个事务中,因为首先我加载Bs,然后在JSF页面上显示它们,然后当用户提交表单时,我创建一个a并持久化它。所以它不在同一个http请求中。或者我应该再装一次吗?不,你不应该再装一次。您使用的是哪个JPA引擎?这种联系是双向的吗?向我们显示两个实体的完整代码以及用于关联它们的代码。