是否可以保存引用未保存代理的实体?
Posted
技术标签:
【中文标题】是否可以保存引用未保存代理的实体?【英文标题】:Is it possible to save an entity that references an unsaved proxy? 【发布时间】:2021-02-27 15:14:02 【问题描述】:背景
我的项目中有两个实体。一个称为“实体”,另一个是关系。我使用它们来模拟游戏中对象之间的关系。所以我的数据库中有某种树/层次结构......但在我的游戏中并非如此。我的实体看起来像这样......@Entity
@Table(name = "entity")
@Access(AccessType.FIELD)
public class EntityPojo implements Serializable
@Id public long id;
@OneToMany(mappedBy = "owner", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
public Set<RelationshipPojo> relations = new LinkedHashSet<>();
@Entity
@Table(name = "relationship")
@Access(AccessType.FIELD)
public class RelationshipPojo
@Id
public long id;
@ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
@JoinColumn(name = "entity_id")
public EntityPojo owner;
@ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
public Set<EntityPojo> targets = new LinkedHashSet<>();
问题
我的游戏内对象之一在引用未保存的实体时可能会被保存。想象一下这种情况......在我的游戏中,我创建了多个游戏对象及其实体 pojo。 然后其中一个(磁贴)被保存,但无法获得未保存对象的代理,这会导致 ObjectNotFoundException。
var tile = new EntityPojo();
tile.id = 1;
var player = new EntityPojo();
player.id = 2;
var proxy = session.getReference(EntityPojo.class, 2L); // Reference to unsaved player
var inTileRelation = new RelationshipPojo();
inTileRelation.name = "inTile";
inTileRelation.owner = tile;
inTileRelation.targets.add(proxy); // ObjectNotFoundException
tile.relations.add(inTileRelation);
// Tile gets saved before player was saved...
syncDatabase.save(tile);
问题
为什么会发生这种情况,我该如何预防?甚至可以通过代理保存对另一个实体的引用吗?只是通过拥有实体将来拥有的 id ?我怎样才能做到这一点?在 SQL 中,我会简单地删除约束以插入 id 本身...这在休眠中可能吗?
【问题讨论】:
【参考方案1】:正如documentation 中所述:
获取实体引用而不初始化其数据
有时称为延迟加载,无需加载实体数据即可获得对实体的引用的能力非常重要。最常见的情况是需要在一个实体和另一个现有实体之间创建关联。
Book book = new Book(); book.setAuthor( entityManager.getReference( Person.class, personId ) );
上面的工作假设实体被定义为允许延迟加载,通常通过使用运行时代理。 在这两种情况下,如果给定实体不引用实际的数据库状态,则稍后将引发异常,当应用程序尝试以任何需要访问其数据的方式使用返回的代理时。
因此,只有当您知道您的数据库有一条具有指定 id 的记录并且您只想建立关系而不实际加载实体时,您才能使用entityManager.getReference
。
【讨论】:
谢谢 ^^ 当我在引用之前保存实体时,它按预期工作。以上是关于是否可以保存引用未保存代理的实体?的主要内容,如果未能解决你的问题,请参考以下文章
数据未保存:对象引用了未保存的瞬态实例 - 在刷新之前保存瞬态实例 [重复]