>我有一个团队记录,数据库中有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与空细节合并.
请赐教:)
谢谢 !
解决方法
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 valuecascade=MERGE
or
cascade=ALL
annotation.For all
entities Y referenced by relationships
from X having the cascade element
valuecascade=MERGE
orcascade=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,
wherecascade=MERGE
orcascade=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()期间,关系的破坏会传播到数据库.