我们在一段代码中保留一个图形,然后有另一个代码,试图检索它。我们用这个Spring bean打开我们的transacitons。任何想要访问数据库的人总是调用这个bean的getGraph()方法。
public class OrientDatabaseConnectionManager {
private OrientGraphFactory factory;
public OrientDatabaseConnectionManager(String path, String name, String pass) {
factory = new OrientGraphFactory(path, name, pass).setupPool(1,10);
}
public OrientGraphFactory getFactory() {
return factory;
}
public void setFactory(OrientGraphFactory factory) {
this.factory = factory;
}
/**
* Method returns graph instance from the factory's pool.
* @return
*/
public OrientGraph getGraph(){
OrientGraph resultGraph = factory.getTx();
resultGraph.setThreadMode(OrientBaseGraph.THREAD_MODE.ALWAYS_AUTOSET);
return resultGraph;
}
}
(我无法完全理解thread_mode,但我认为它不应该与问题有关。)
持久保存图表的代码提交和关闭,如下所示:
OrientDatabaseConnectionManager connMan; //this is an injected bean from above.
public boolean saveGraphToOrientDB(
SparseMultigraph<SocialVertex, SocialEdge> graph, String label) {
boolean isSavedCorrectly = false;
OrientGraph graphO = connMan.getGraph();
try {
graphDBinput.saveGraph(graph, label, graphO);
// LOG System.out.println("Graph was saved with label "+label);
isSavedCorrectly = true;
} catch (AlreadyUsedGraphLabelException ex) {
Logger.getLogger(GraphDBFacade.class.getName()).log(Level.SEVERE, null, ex);
} finally {
graphO.shutdown(); //calls .commit() automatically normally, but commit already happens inside.
}
return isSavedCorrectly;
}
这个提交工作得很好 - 数据总是保持不变,我每次都在orientdb管理界面中检查,第一个持久化图表总是可见的。值得注意的是,在保存期间,使用的标签定义了新类(因此根据我的理解修改了模式)并将其用于持久化图。
图表的检索看起来像这样:
@Override
public SocialGraph getSocialGraph(String label) {
OrientGraph graph = connMan.getGraph();
SocialGraph socialGraph = null;
try {
socialGraph = new SocialGraph(getAllSocialNodes(label, graph), getAllSocialEdges(label, graph));
} catch (Exception e) {
logger.error(e);
} finally {
graph.shutdown();
}
return socialGraph;
}
public List<Node> getAllSocialNodes(String label, OrientGraph graph) {
return constructNodes(graphFilterMan.getAllNodesFromGraph(label, graph));
}
public Set<Vertex> getAllNodesFromGraph(String graphLabel, OrientGraph graph) {
Set<Vertex> labelledGraph = new HashSet<>();
try{
Iterable<Vertex> configGraph = graph.getVerticesOfClass(graphLabel);
for(Vertex v : configGraph){ //THE CODE CRASHES HERE, WITH "CLASS WITH NAME graphLabel DOES NOT EXIST
labelledGraph.add(v);
}
} catch(Exception ex){
logger.error(ex);
graph.rollback();
}
return labelledGraph;
}
所以问题是,当我们用一个新的类坚持一个新图时,比如说#34; graph01&#34;然后我们想要检索它,它没关系。之后,我们创建了一个&#34; graph02&#34;我们想要检索它,但它崩溃了,正如上面评论的那样 - OrientDb告诉你,那个类带有&#34; graph02&#34;名称不存在。
当时它确实存在于管理界面中,但是,当我调试时,在调用factory.getTx()
后,该类实际上不在模式中
刚开始时,当我们从工厂获得一个事务图实例时,我们得到一个带有上下文的图形,其中rawGraph的底层数据库的元数据具有模式代理委托模式共享类没有新类,我可以看到它在数据库中提交。
架构中应该还有一个类。之前持久化(并提交)的那个 - 也可以在orientDb管理界面中看到(不存在于变量中)
我认为正在发生的事情是,工厂从中获取事务的池在某种程度上缓存了模式。当我们添加一个新类时,它不会刷新模式。
当我们尝试获取新图时,为什么架构不显示新类?架构不会刷新吗?
我找到了here in schema documentation
注意:对架构的更改不是事务性的,因此请在事务外部执行它们。
那么我们应该在事务之外创建新类,然后我们会在上下文中获得模式的更新吗?
//也许我理解错误的概念 - 昨天我与OrientDb有联系,我将在已编写的代码中找出问题。
我们使用的Db是remote:localhost/socialGraph
OrientDB版本1.7.4
答案 0 :(得分:1)
我们在代码中注意到同一问题,在池化连接中架构更改不可见。
我们还有一种获得连接的工厂。我们所做的是保留一个模式版本号,每次我们有一些改变模式的操作时,我们都会计算数字,当打开一个新连接时,我们检查模式版本,如果它被更改。
更改架构后,我们重新加载架构,关闭池并重新创建它。该方法已被证明可以使用(我们目前的版本为2.0.15)。
以下是相关代码:
private static volatile int schemaVersion = -1;
private OPartitionedDatabasePool pool;
protected void createPool() {
pool = new OPartitionedDatabasePool(getUrl(), getUsername(), getPassword());
}
@Override
public synchronized ODatabaseDocumentTx openDatabase() {
ODatabaseDocumentTx db = pool.acquire();
//DatabaseInfo is a simple class put in a static contect that holds the schema version.
DatabaseInfo databaseInfo = CurrentDatabaseInfo.getDatabaseInfo();
ODocument document = db.load((ORID) databaseInfo.getId(), "schemaVersion:0", true);
Integer version = document.field("schemaVersion");
if (schemaVersion == -1) {
schemaVersion = version;
} else if (schemaVersion < version) {
db.getMetadata().getSchema().reload();
schemaVersion = version;
pool.close();
createPool();
db = pool.acquire();
}
return db;
}
答案 1 :(得分:0)
最后问题是,我们有两个liferay项目,每个项目在WAR文件中都有自己的spring应用程序上下文,当我们在Liferay中将这些项目部署为portlet时,这两个项目创建了两个上下文,每个上下文都有一个OrientDatabaseConnectionManager。
在一个上下文中,架构正在被更改。即使我重置连接并重新加载模式,它也只发生在一个上下文中的连接管理器/工厂。检索图是在另一个项目的portlet中发生的,导致一个过时的模式(没有重新加载,因为重新加载发生在其他弹簧上下文中) - 因此错误。
所以你必须要小心 - 要么为所有portlet共享一个spring应用程序上下文和bean(通过拥有父应用程序上下文,you can read more about it here)
OR
检查同一项目中架构的变化,稍后您将用它来检索数据。