Hibernate Simulated Persistence:持久性和提交之间有什么可能?
Hibernate Simulated Persistence: What is possible between persistence and commit?
我目前正在为混合来源的对象编写模拟上下文。其中一些对象是从数据库加载的持久性休眠实体。其他是临时创建的新 'simulated' 对象,稍后可能会存储在数据库中。
本应用程序处理有向图,这些图是使用 Hibernate 实体从数据库加载的。目前它只是检查循环子结构。映射是这样安排的,它从数据库中延迟加载 Nodes
和 Edges
。这允许我的循环检查器根据存储在直接相关 Edges
.
中的信息通过延迟获取相邻 Nodes
来遍历整个图
Node {
Integer id; // mapped id
List<Edge> edges; // mapped and fetched lazy
}
Edge {
Integer id; // mapped id
Integer predecessorId; // mapped
Integer successorId; // mapped
Node predecessor; // mapped and fetched lazy
Node successor; // mapped and fetched lazy
}
现在我想在图中添加一条边,而不将其存储在数据库中。无论如何,CycleChecker
应该首先 运行,但要考虑到优势。我想知道我是否可以重用现有的 CycleChecker
并完全使用 Hibernate 实体解决该问题,而不必为 "simulated" 实体编写额外的代码。
两个问题:
如果我创建一个新的 Edge
并将其持久保存在 Hibernate Session
中(比如受事务上下文限制),我是否能够延迟加载其 Node
commit() 之前来自数据库的后继者?
如果我创建一个新的 Node
并将其保存在会话中(没有提交或刷新发生),Hibernate 会通过 get(Id)
或从另一个新的延迟加载找到它Edge
?
如果这一切都不可能,是否有一种 Hibernate 方法可以连接到提取中,以便从我的模拟上下文中 return 对象?
当我们使用与 Hibernate 实体一起工作的算法(并依赖于 Hibernate 延迟加载关系)时,我不久前制定了这个解决方案。模拟启动事务并持久化所有对象以进行模拟。所有模拟对象都必须首先从缓存中逐出,否则延迟关系加载将无法工作。计算完成后,可以停止模拟,即回滚事务。详情见我的代码:
public class SimulationContext {
private Session session = null;
private Transaction transaction = null;
private List<Simulateable> simulatedObjects;
public SimulationContext() {
this.simulatedObjects = new ArrayList<Simulateable>();
}
/** ... add, remove, clear, ... */
/**
* Start simulation: Start transaction and persist simulation entities.
* @param session
*/
public void start(Session session) {
if (this.session != null) {
this.stop();
}
this.session = session;
this.transaction = session.beginTransaction();
// Initializing simlation context, persisting simulated objects
for (Simulateable object : simulatedObjects) {
// persist object ...
session.persist(object);
session.flush();
// ... and remove it from session cache (otherwise lazy loaded objects referenced by foreign keys might not get loaded)
session.evict(object);
}
}
/**
* Stop simulation: Roll-back the transaction and close the session.
*/
public void stop() {
transaction.rollback();
transaction = null;
session = null;
}
}
我目前正在为混合来源的对象编写模拟上下文。其中一些对象是从数据库加载的持久性休眠实体。其他是临时创建的新 'simulated' 对象,稍后可能会存储在数据库中。
本应用程序处理有向图,这些图是使用 Hibernate 实体从数据库加载的。目前它只是检查循环子结构。映射是这样安排的,它从数据库中延迟加载 Nodes
和 Edges
。这允许我的循环检查器根据存储在直接相关 Edges
.
Nodes
来遍历整个图
Node {
Integer id; // mapped id
List<Edge> edges; // mapped and fetched lazy
}
Edge {
Integer id; // mapped id
Integer predecessorId; // mapped
Integer successorId; // mapped
Node predecessor; // mapped and fetched lazy
Node successor; // mapped and fetched lazy
}
现在我想在图中添加一条边,而不将其存储在数据库中。无论如何,CycleChecker
应该首先 运行,但要考虑到优势。我想知道我是否可以重用现有的 CycleChecker
并完全使用 Hibernate 实体解决该问题,而不必为 "simulated" 实体编写额外的代码。
两个问题:
如果我创建一个新的
Edge
并将其持久保存在 HibernateSession
中(比如受事务上下文限制),我是否能够延迟加载其Node
commit() 之前来自数据库的后继者?如果我创建一个新的
Node
并将其保存在会话中(没有提交或刷新发生),Hibernate 会通过get(Id)
或从另一个新的延迟加载找到它Edge
?
如果这一切都不可能,是否有一种 Hibernate 方法可以连接到提取中,以便从我的模拟上下文中 return 对象?
当我们使用与 Hibernate 实体一起工作的算法(并依赖于 Hibernate 延迟加载关系)时,我不久前制定了这个解决方案。模拟启动事务并持久化所有对象以进行模拟。所有模拟对象都必须首先从缓存中逐出,否则延迟关系加载将无法工作。计算完成后,可以停止模拟,即回滚事务。详情见我的代码:
public class SimulationContext {
private Session session = null;
private Transaction transaction = null;
private List<Simulateable> simulatedObjects;
public SimulationContext() {
this.simulatedObjects = new ArrayList<Simulateable>();
}
/** ... add, remove, clear, ... */
/**
* Start simulation: Start transaction and persist simulation entities.
* @param session
*/
public void start(Session session) {
if (this.session != null) {
this.stop();
}
this.session = session;
this.transaction = session.beginTransaction();
// Initializing simlation context, persisting simulated objects
for (Simulateable object : simulatedObjects) {
// persist object ...
session.persist(object);
session.flush();
// ... and remove it from session cache (otherwise lazy loaded objects referenced by foreign keys might not get loaded)
session.evict(object);
}
}
/**
* Stop simulation: Roll-back the transaction and close the session.
*/
public void stop() {
transaction.rollback();
transaction = null;
session = null;
}
}