Jpa EntityManager正在尝试在没有提示的情况下插入实体

Jpa EntityManager正在尝试在没有提示的情况下插入实体,jpa,eclipselink,Jpa,Eclipselink,也许我只是给了你一小段代码(如果是这样的话,我会发布更多)而过分简化了这一点,但我认为,一开始,越少越好: 我有一个Asset类型的实体,它有一个Location类型的字段,也是一个实体。设置资产的位置时,还必须设置其子项的位置 Location location = asset.getLocation(); em.merge(location); em.flush(); childAsset.setLocation(asset.getLocation()); em.flush(); 当我运

也许我只是给了你一小段代码(如果是这样的话,我会发布更多)而过分简化了这一点,但我认为,一开始,越少越好:

我有一个Asset类型的实体,它有一个Location类型的字段,也是一个实体。设置资产的位置时,还必须设置其子项的位置

Location location = asset.getLocation();
em.merge(location);
em.flush();

childAsset.setLocation(asset.getLocation());
em.flush();
当我运行flush()时,会出现以下异常:

内部异常:java.sql.SQLIntegrityConstraintViolationException:ORA-00001:违反了唯一约束(SWRADMIN.LOCATION\u PK)

我的问题是…为什么这个位置对象甚至试图被持久化?我所做的就是在实体中设置一个变量

这在以前工作得很好,但我们刚刚切换到使用Eclipselink和JavaEE6,这个问题就出现了

解决方案:我使用了从下面“分离”的想法,并做了以下更改:

Location location = asset.getLocation();

em.detach(childAsset);
childAsset.setLocation(asset.getLocation());
em.merge();
em.flush();

成功了!我不明白为什么…你会认为自动同步会做同样的事情。

那么,位置是现有位置还是新对象

它是如何读取的,是从另一个事务或实体管理器读取的,还是以某种方式分离的?如果是这样,那么您需要重新读取(查找)或合并它


如果该对象是新的且与托管对象相关,则“是”,flush必须将其写入。

如果该对象处于托管状态,则实体管理器将通过隐式(可能在事务结束时)或显式(在调用
em.flush()
方法时)将其与基础数据库同步

可以使用
em.detach(entity)
拆离单个图元,也可以使用
em.clear()
拆离所有图元。然后,对一个或多个实体所做的更改将不会反映在数据库中

为了更好地处理这个问题,您可以使用BMT(Bean管理的事务),您必须手动处理实体持久性事务

编辑:

Location location = asset.getLocation();
childAsset.setLocation(location);
em.merge(childAsset);
em.flush();

从代码看,您似乎正在使用位置的非托管版本,并将其与子资产相关联。如果您的childAsset->Location关系被标记为cascade persist,则在flush或commit时将在Location上调用spec Required perist。由于位置不是托管对象,因此需要在持久化时出现异常

管理位置时(例如,在ChildAsset上调用merge或使用从 em.merge(location);call),对ChildAsset->location的持久化操作是不可操作的


不要将非托管实体与标记为cascade persist的关系相关联

嗨,詹姆斯。我在帖子中添加了更多代码。该位置是现有位置。为了确定,我对location对象执行了merge(),然后执行了flush()。它工作得很好。当我将它分配给childAsset,然后执行另一个flush()时,我得到了相同的错误。因此,我执行了em.detach(childAsset),然后是childAsset.setLocation(location),然后是em.merge(childAsset),结果成功了!我的问题是…为什么?这不是同步开始时应该做的事情吗?查看原始代码,em.merge(location)&然后em.flush()将在数据库中持久化“location”,然后在childAsset中设置它&然后刷新再次引发“SQLIntegrityConstraintViolationException”,因为“location”已经存在于数据库中。修改答案,请参阅编辑部分。