我遇到了一个主要问题,即jpa / hibernate块是不完整的,因为这意味着滞后。在保存,更新或加载操作期间,玩家无法与游戏互动几秒钟。
我试图将这些操作简单地包装在额外的线程中,效果不佳...
我当前的数据库流如下...
// Clone entities, chunk ( see below )
// Run the database operation for updating the entities async in a new thread, return updated entities once done
return CompletableFuture.runAsync(() -> {
var session = database.openSession();
session.beginTransaction();
try {
// Save identities first
for (var identity : identities)
session.update(identity);
// Update components, each component-type
for(var insertedClass : insertationOrder)
for (var hbc : componentsPerType.get(insertedClass))
session.update(hbc);
session.flush();
session.clear();
session.getTransaction().commit();
} catch (Exception e){
var messageComposer = new ExceptionMessageComposer(e);
GameExtension.getInstance().trace("Update : "+messageComposer.toString());
session.getTransaction().rollback();
}
session.close();
}).thenApply(v -> entities);
/**
* A component which marks a {@link com.artemis.Entity} as a chunk and stores its most valuable informations.
*/
@Entity
@Table(name = "chunk", uniqueConstraints = {@UniqueConstraint(columnNames={"x", "y"})}, indexes = {@Index(columnList = "x,y")})
@Access(value = AccessType.FIELD)
@SelectBeforeUpdate(false)
public class Chunk extends HibernateComponent{
public int x;
public int y;
public Date createdOn;
@OneToMany(fetch = FetchType.EAGER)
@JoinTable(name = "chunk_identity", joinColumns = @JoinColumn(name = "identity_id"), inverseJoinColumns = @JoinColumn(name = "id"), inverseForeignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT))
@Fetch(FetchMode.JOIN)
@BatchSize(size = 50)
public Set<Identity> inChunk = new LinkedHashSet<>();
@Transient
public Set<ChunkLoader> loadedBy = new LinkedHashSet<>();
public Chunk() {}
public Chunk(int x, int y, Date createdOn) {
this.x = x;
this.y = y;
this.createdOn = createdOn;
}
}
/**
* Represents a ID of a {@link com.artemis.Entity} which is unique for each entity and mostly the database id
*/
@Entity
@Table(name = "identity")
@Access(AccessType.FIELD)
@SQLInsert(sql = "insert into identity(tag, typeID, id) values(?,?,?) ON DUPLICATE KEY UPDATE id = VALUES(id), tag = values(tag), typeID = values(typeID)")
@SelectBeforeUpdate(value = false)
public class Identity extends Component {
@Id public long id;
public String tag;
public String typeID;
public Identity() {}
public Identity(long id, String tag, String typeID) {
this.id = id;
this.tag = tag;
this.typeID = typeID;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
var identity = (Identity) o;
return id == identity.id;
}
@Override
public int hashCode() {
return Objects.hash(id, tag, typeID);
}
}
我看到很多其他的帖子都在问类似的问题,但是没有一个是一个真实而良好的例子,尤其是在保存和更新方面。
那么,我们如何在一个额外的线程中运行保存和更新操作,而又不丢失集合跟踪并运行到“ ConcurrentModificationException”的容器中?
任何代码示例吗?