Search code examples
orientdb

How to organize OrientDB DAO in case of transactions in multithreaded environment?


I try to organize architecture of my DAO with OrientDB.
Below - example of my:

Connection manager:

public class DB {

    private static final OPartitionedDatabasePoolFactory poolFactory = new OPartitionedDatabasePoolFactory();

    public static ODatabaseDocumentTx fromPool() {
        return poolFactory.get(sDbUrl, sDbUser, sDbPassword).acquire();
    }
}

Dao (it uses in multithreaded environment):

public class Dao {

    public static void addGold(String rid, long gold) {
        try (ODatabaseDocumentTx db = DB.fromPool()) {
            final String updateQuery = "UPDATE " + rid + " INCREMENT gold = " + gold + " LOCK RECORD";
            db.command(new OCommandSQL(updateQuery)).execute();
        }
    }

    public static void removeGold(String rid, long gold) {
        try (ODatabaseDocumentTx db = DB.fromPool()) {
            final String updateQuery = "UPDATE " + rid + " INCREMENT gold = " + -gold + " LOCK RECORD";
            db.command(new OCommandSQL(updateQuery)).execute();
        }
    }

    public static String transferGold(String fromRid, String toRid, long gold) {
        try (ODatabaseDocumentTx db = DB.fromPool()) {
            int numTries = 100;
            while (true) {
                try {
                    db.begin(OTransaction.TXTYPE.OPTIMISTIC);
                    removeGold(fromRid, gold);
                    addGold(toRid, gold);
                    db.commit();
                    return "ok";
                } catch (OConcurrentModificationException e) {
                    db.rollback();
                    if (--numTries == 0) {
                        return "error";
                    }
                }
            }
        }
    }
}

It's valid to get connection from pool in case of transaction? So same database instance will be returns in same thread?

Any other advice are welcome


Solution

  • Using the OPartitionedDatabasePool should be thread safe and provide a way to get your connections. I think the OPartitionedDatabasePoolFactory is only used if you want to create multiple OPartitionedDatabasePool instances.

    A static instance of OPartitionedDatabasePool:

    OPartitionedDatabasePool myPool = new OPartitionedDatabasePool(dbUrl, user, password);
    

    And then anytime a thread needs a connection:

    ODatabaseDocumentTx dbConnection = MyClass.myPool.acquire();
    

    (As in your code with OPartitionedDatabasePoolFactory).

    The pool should automatically handle getting a database connection that will function on your thread.