Java 如何更新深度克隆实体? 描述
我正在开发一个小的java游戏服务器。。。为了在另一个线程中更新和保存游戏,我不得不深度克隆我的一些实体。发生内部休眠异常的其他情况:Java 如何更新深度克隆实体? 描述,java,spring,multithreading,hibernate,jpa,Java,Spring,Multithreading,Hibernate,Jpa,我正在开发一个小的java游戏服务器。。。为了在另一个线程中更新和保存游戏,我不得不深度克隆我的一些实体。发生内部休眠异常的其他情况: 因此,我的流程目前看起来如下所示: 标记要更新的游戏实体 将这些实体传递到另一个线程 克隆这些实体 对克隆的实体调用“session.update” 一分钟后重复 它在简单类中工作得很好,但在关系方面存在一个巨大的问题 问题 当我深度克隆我的“chunk”实体(见下文)时,它的集合(inChunk)也会被深度克隆。 我使用深度克隆实体并将其传递给“sessi
因此,我的流程目前看起来如下所示:
- 标记要更新的游戏实体
- 将这些实体传递到另一个线程
- 克隆这些实体
- 对克隆的实体调用“session.update”
- 一分钟后重复
//运行数据库操作以在新线程中异步更新实体,完成后返回更新的实体
返回CompletableFuture.runAsync(()->{
var session=database.openSession();
session.beginTransaction();
试一试{
//保存实体
对于(var实体:实体)
更新(实体);
session.flush();
session.clear();
session.getTransaction().commit();
}捕获(例外e){
var messageComposer=新的例外消息编写器(e);
GameExtension.getInstance().trace(“更新:+messageComposer.toString());
session.getTransaction().rollback();
}
session.close();
})。然后应用(v->entities);
@实体
@表(name=“chunk”,uniqueConstraints={@UniqueConstraint(columnNames={“x”,“y”}),索引={@Index(columnList=“x,y”)})
@访问权限(值=AccessType.FIELD)
@选择BeforeUpdate(false)
公共类块扩展了HibernateComponent{
公共int x;
公共智力;
公开日期;
@OneToMany(fetch=FetchType.EAGER)
@JoinTable(name=“chunk\u identity”,joinColumns=@JoinColumn(name=“identity\u id”),inverseJoinColumns=@JoinColumn(name=“id”),inverseForeignKey=@ForeignKey(ConstraintMode.NO\u CONSTRAINT))
@Fetch(FetchMode.JOIN)
@批量大小(大小=50)
public Set inChunk=new LinkedHashSet();
@短暂的
public Set loadedBy=new LinkedHashSet();
公共块(){}
公共块(int x,int y,Date createdOn){
这个.x=x;
这个。y=y;
this.createdOn=createdOn;
}
}
/**
*表示{@link com.artemis.Entity}的ID,该ID对于每个实体都是唯一的,主要是数据库ID
*/
@实体
@表(name=“identity”)
@访问权限(AccessType.FIELD)
@SQLInsert(sql=“在重复密钥更新id=values(id),tag=values(tag),typeID=values(typeID)”上插入标识(tag,typeID,id)值(?,,?)
@选择BeforeUpdate(值=false)
公共类标识扩展组件{
@Id公共长Id;
公共字符串标签;
公共字符串类型ID;
公共标识(){}
公共标识(长id、字符串标记、字符串类型id){
this.id=id;
this.tag=tag;
this.typeID=typeID;
}
}
问题:
为什么hibernate总是插入我的孩子而不检查他们是否已经插入?我能做些什么来防止/解决这个问题
我尝试过的事情
- 正在删除“@SelectBeforeUpdate”批注
- 将级联添加到“Chunk.InChunk”与“All”或“Merge”的关系中
- 运行“session.merge”而不是“session.update”,这会导致相同的重复条目异常,只需忽略其子项已插入的事实
如果需要更多信息,请写评论。这是一个复杂的问题,很难概括,但我希望我已经正确地描述了它。
你应该考虑实现两个主要的变化:
- 仅包含接口的API模块,例如跨以下两个模块强制使用统一的get方法
- Writer模块,使用所有的Hibernate魔法来编写实体和一种侦听器模式,这样下一个模块就可以注册自己了
- 具有Hibernate magic的读卡器模块,用于读取实体并将其提供给其他人(通过REST、RCP等),向编写器注册自身,以便在发生更改时进行某种刷新