Reputation: 574
We are in the process of changing some of the applications that use a relation database, to OrientDB (2.1.9). This transaction will be made in small steps, we will first start with the JDBC driver approach, and maybe we will switch to a native implementation later.
We have an application that is based on Spring Integration, where we changed from an Oracle Database to OrientDB, using the JDBC driver.
The database connections are managed by Tomcat 8 Connection Pool, and the transactional behavior is handled by Spring's Transaction Manager:
<bean id="dataSource" class="org.apache.tomcat.jdbc.pool.DataSource" destroy-method="close">
<property name="driverClassName" value="com.orientechnologies.orient.jdbc.OrientJdbcDriver" />
...
</bean>
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
After changing the database to OrientDB, we encountered the following error:
com.orientechnologies.orient.core.exception.ODatabaseException: Database instance is not set in current thread. Assure to set it with: ODatabaseRecordThreadLocal.INSTANCE.set(db);
The OrientDB documentation, on Multi threading, states:
OrientDB supports multi-threads access to the database. ODatabase* and OrientGraph* instances are not thread-safe, so you've to get an instance per thread and each database instance can be used only in one thread per time. For more information about how concurrency is managed by OrientDB look at Concurrency.
Since v2.1 OrientDB doesn't allow implicit usage of multiple database instances from the same thread. Any attempt to manage multiple instances in the same thread must explicitly call the method db.activateOnCurrentThread() against the database instance BFORE you use it.
This posed a problem, as all the database connection management is handled by the connection pool (as it should be). So, in order to implement the solution proposed by OrientDB, I had to have access to the underlying ODatabaseDocumentTx database, in order to apply the activateOnCurrentThread() method.
To be able to do it, I had to create a wrapper from both the JDBC driver class, and the OrientJdbcConnection.
In the OrientJdbcConnection, I obtained the underlying database by the use of Java Reflection:
public class OrientJdbcConnectionWrapper extends OrientJdbcConnection {
@Override
public void commit() throws SQLException {
final ODatabaseDocumentTx database = getPrivateDatabaseFieldByReflection();
database.activateOnCurrentThread();
super.commit();
}
And the JDBC Driver class wrapper, now returns a wrapped connection: public class OrientJdbcDriverWrapper extends OrientJdbcDriver {
public Connection connect(final String url, final Properties info) throws SQLException {
if (!acceptsURL(url)) {
throw new SQLException(DO_NOT_ACCEPT_URL_ERROR + url);
}
return new OrientJdbcConnectionWrapper(url, info);
}
}
Finally, the configuration of the Connection pool now uses the wrapped driver:
<bean id="dataSource" class="org.apache.tomcat.jdbc.pool.DataSource" destroy-method="close">
<property name="driverClassName" value="x.y.z.driver.orientdb.OrientJdbcDriverWrapper" />
</bean>
As expected, this works perfectly, but i'm not entirely sure that this is the correct way to do it as i haven't see anyone with this issue.
On the other hand, the OrientDB documentation does suggest the use of activateOnCurrentThread() on a multi-threading environment.
Upvotes: 1
Views: 815
Reputation: 574
OrientDB has its own database pool, that can be easily configured:
<bean id="dataSource" class="com.orientechnologies.orient.jdbc.OrientDataSource">
<constructor-arg name="url" value="jdbc:orient:plocal:xx\\databases\\test" />
<constructor-arg name="username" value="xx"/>
<constructor-arg name="password" value="xx"/>
<constructor-arg name="info" ref="databaseProperties" />
</bean>
<util:map id="databaseProperties" value-type="java.lang.String">
<entry key="db.usePool" value="true" />
<entry key="db.pool.min" value="1" />
<entry key="db.pool.max" value="10" />
Note: I'm using OrientDB through its orient-jdbc driver.
Upvotes: 0