java - 提交并关闭事务后,将新类添加到图表中 - 新的 Tx 在模式中看不到该类,尽管它已被持久化

标签 java orientdb

我们将一个图表保存在一段代码中,然后使用另一个代码来尝试检索它。我们用这个 Spring bean 来打开我们的交易。任何想要访问数据库的人总是调用此 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;
}

所以问题是,当我们用新类持久化一个新图时,说“graph01”,然后我们想要检索它,它就可以了。后来,我们创建了一个“graph02”,我们想要检索它,但它崩溃了,正如上面评论的那样 - OrientDb 告诉您,名称为“graph02”的类不存在。

当时它确实存在于管理界面中,但是,当我调试时,该类实际上不在调用factory.getTx()之后的架构中

一开始,当我们从工厂获取事务图实例时,我们得到一个具有上下文的图,其中 rawGraph 的底层数据库元数据具有模式代理委托(delegate)模式共享类,而没有新类,其中我显然可以在数据库中看到提交。

或者在图片上: enter image description here

架构中应该多一个类。不久前持久化(并提交)的一个 - 也可以在 orientDb 管理界面中看到(不存在于变量中)

我认为正在发生的事情是工厂从中获取事务的池具有某种缓存模式或其他内容。当我们添加新类时,它不会刷新架构。

当我们尝试获取新图表时,为什么模式不显示新类?架构没有刷新吗?

我找到了here in schema documentation那个

NOTE: Changes to the schema are not transactional, so execute them outside a transaction.

那么我们应该在事务之外创建新类,然后我们会在上下文中获得架构更新吗?

//也许我对概念的理解是错误的 - 我昨天才接触到 OrientDb,我要在已经编写的代码中找出问题。

我们使用的数据库是remote:localhost/socialGraph OrientDB 1.7.4版本

最佳答案

我们在代码中注意到同样的问题,架构更改在池连接中不可见。

我们还有一种可以建立连接的工厂。我们所做的是保留架构版本号,每次进行更改架构的操作时,我们都会更改该版本号,并且当打开新连接时,我们会检查架构版本(如果已更改)。

当架构更改时,我们重新加载架构,关闭池并重新创建它。该方法已被证明有效(我们目前使用的是 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;
}

关于java - 提交并关闭事务后,将新类添加到图表中 - 新的 Tx 在模式中看不到该类,尽管它已被持久化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32885806/

相关文章:

java - 尝试检测 ActionMode 内存泄漏

java - 无法从日期格式中仅获取日期?

java - 连续因素检验

java - OrientDB中批量插入

java - 非法参数异常 : Failed to serialize object

Neo4j vs OrientDB 对象映射选项 vs Tinkerpop Frames

java - 寻找与 JPA 模型交互的通用库

java - 调用两个数据库服务器的最佳方法

java - OrientDB 服务器部分忽略 ORIENTDB_HOME

neo4j - Tinkerpop 蓝图顶点查询