以下是导致问题的序列:
>我有一个团队记录,数据库中有3个玩家记录. Team实体有一个使用FetchType.LAZY,CascadeType.ALL的List >单击webui上的搜索按钮 >调用服务器端使用JPA查询的查询,查找所有Team记录,在这种情况下,只查询从查询??返回的团队实体的1条记录(其中包含播放器实体列表的代理) >将此teamEntity映射到DTO,并将此DTO返回到webui,跳过播放器实体列表的映射 > Webui以html格式呈现DTO,准备接收用户的修改 >用户修改团队的属性,例如团队成立的日期 >单击webui上的保存按钮 >将DTO转换为团队实体,用于更新现有团队记录 >但是在这种情况下,如果我要使用em.merge(teamEntity),团队记录将会更新,但是玩家列表会发生什么?因为从DTO转换到团队实体时,teamEntity有一个空的玩家实体列表.合并后,我注意到teamEntity的大小为0.但在刷新该实体em.refresh(teamEntity)后,它将返回3个细节大小.
我很困惑:
>合并后为什么大小为0?这就像不再代表记录了 >在进行测试之前,我认为细节将被删除,因为我将teamEntity与空细节合并.
请赐教:)
谢谢 !
解决方法
JPA规范说:
The semantics of the merge operation applied to an entity X are as follows:
-
If X is a detached entity,the state of X is copied onto a pre-existing managed entity instance X’ of the same identity or a new managed copy X’ of X is created.
-
If X is a new entity instance,a new managed entity instance X’ is created and the state of X is copied into the new managed entity instance X’.
-
If X is a removed entity instance,an IllegalArgumentException will be thrown by the merge operation (or the transaction commit will fail).
-
If X is a managed entity,it is ignored by the merge operation,however,the merge operation is cascaded to entities referenced by relationships from X if these relationships have been annotated with the cascade element value cascade=MERGE or cascade=ALL annotation.
-
For all entities Y referenced by relationships from X having the cascade element value cascade=MERGE or cascade=ALL ,Y is merged recursively as Y’. For all such Y referenced by X,X’ is set to reference Y’. (Note that if X is managed then X is the same object as X’.)
-
If X is an entity merged to X’, with a reference to another entity Y, where cascade=MERGE or cascade=ALL is not specified,then navigation of the same association from X’ yields a reference to a managed object Y’ with the same persistent identity as Y.
如你所见,这里没有魔力.已分离实例的状态将复制到新创建的托管实例中.由于您的分离实例有一个空列表,因此托管实例也会拥有它.
进一步的行为取决于关系的所有权,因为数据库中的表示反映了关系的拥有方:
>如果Team是拥有者,那么团队和玩家之间的关系将在刷新期间被销毁(但是除非你的关系中有orphanRemoval = true,否则玩家本身会存活). >否则在Team中拥有空列表不会影响数据库.
如果在刷新上下文之前刷新团队,则Team的所有属性都将由数据库中的值重写,因此将恢复播放器列表(因为尚未刷新播放器的空列表).
如果在调用refresh()之前调用flush(),并且Team是拥有者,则list将为空,因为在flush()期间,关系的破坏会传播到数据库.
(编辑:李大同)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|