Neo4j Dynamic cql switching - jdbc

I want to switch database based on a request header, which I have managed to do but in a rather clunky way.
I had to change my jdbc driver to neo native driver to get the "USE database" prefix to work.
I had to prefix my cql query with "USE database "
What I really want is to do this via AOP, such that I can annotate the method with my custom java annotation and this aspect will just call "USE DATABASE" in isolation before going on to the joinpoint and calling the actual query.
When I try this though I get this error
Query cannot conclude with USE GRAPH (must be RETURN or an update clause)
Is it possible ?

You can change the database on the session object.
try (Session session = driver.session(SessionConfig.forDatabase( "databaseName" ))) {
session.executeWrite((tx) -> tx.run(stmt, params));
}
You shouldn't use JDBC for apps, that's rather for tools.
https://neo4j.com/docs/java-manual/current/cypher-workflow/#java-database-selection

Related

jtds.jdbc.JtdsConnection.createBlob java.lang.AbstractMethodError

mvn:net.sourceforge.jtds/jtds/1.3.1-patch-20190523/jar
to save to a Microsoft SQL Server database.
Actually this JDBC driver is provided by Talend. For various reasons, I have some Java JDBC code which saves blobs to the database. This works fine with an Oracle DB.
try (Connection con = DriverManager.getConnection(this.connectionString, this.user, this.pw)) {
insert(con, ags, snr, productVersion, nummer, inhalt, this.migrationsBenutzer, format, daten);
}
public long insert(Connection con, String ags, String snr, int productVersion ,int nummer,String inhalt, String benutzer, String format, byte[] daten) throws SQLException {
long result = 0;
String timestamp = now();
try {
Blob blob = con.createBlob();
blob.setBytes(1, daten);
PreparedStatement ps = con.prepareStatement(this.insert);
...
ps.setBlob(9, blob);
result = ps.executeUpdate();
However when I call the method with a connection string for jtds:
jdbc:jtds:sqlserver://:1433;databaseName=
I get this exception
Exception in thread "main" java.lang.AbstractMethodError
at net.sourceforge.jtds.jdbc.JtdsConnection.createBlob(JtdsConnection.java:2776)
at de.iteos.dao.BildspeichernDAO.insert(BildspeichernDAO.java:60)
What can I do? If feasible I want to keep the method a generic as possible. Do I have to switch to another JDBC driver? I have read somewhere that this could be solved with a validation query. For this I would have to implement two different DataSources for Oracle and SQL Server right?
The problem is that jTDS is - as far as I know - no longer maintained, and available versions are stuck on JDBC 3.0 (Java 1.4) support. The method Connection.createBlob you're trying to call was introduced in JDBC 4.0 (Java 6). Attempts to call this method on a driver that was compiled against the JDBC 3.0 API will result in AbstractMethodError as the method from JDBC 4.0 (or higher) is not implemented.
The simplest and best solution is probably to switch to the Microsoft SQL Server JDBC driver.
Alternatively, you need to switch to the JDBC 3.0 options for populating a blob, that is, using the PreparedStatement.setBinaryStream(int, InputStream, int) method (not to be confused with setBinaryStream(int, InputStream) or setBinaryStream(int, InputStream, long) introduced in JDBC 4.0!), or possibly setBytes(int, byte[]), or using driver specific methods for creating blobs.
The validation query solution you mention doesn't apply here, that solves a problem with Connection.isValid that the data source implementation in some Tomcat versions calls by default, unless you configure a validation query. It has the same underlying cause (the isValid method was also introduced in JDBC 4.0).
I'm not sure what you mean with "I would have to implement two different DataSources for Oracle and SQL Server right?", you cannot use one and the same data source for two different databases, so you would need to configure two different instances anyway.

How can I globally set Oracle fetch size in my Scala Play (Anorm) application?

Our DBAs would like me to increase the fetch size from the JDBC's default (10). Is there a way to do this globally via application.conf, JDBC URL or similar?
My DB calls essentially look like
object SomeController extends Controller {
def someMethod(acronym: String) = Action { implicit request =>
DB.withConnection { implicit c =>
val cust = SQL("""select whatever.... where acronym = {acronym}""").on("acronym" -> acronym).apply()
But there's a lot of them over many controllers and methods.
What can be done to have a central setting?
defaultRowPrefresh is an Oracle JDBC driver property than can be set to change from the default of 10 (Table 4-2 Connection Properties Recognized by Oracle JDBC Drivers)
While not explicitly documented, it looks like custom JDBC properties are done under the datasource key (see this and this)
So something like db.default.datasource.defaultRowsPrefetch="100" should work.
After some searching through the Oracle JDBC jar, I found:
ojdbc6-unjar $ cat ./oracle/jdbc/defaultConnectionProperties.properties
# This properties file sets the default value for connection properties.
# Entries in this file override the predefined defaults as specified
# in the JavaDoc for oracle.jdbc.OracleConnection. These defaults are
# themselves overridden by any values set via -D which are overridden
# by values passed in the Properties argument to getConnection.
#
This bit and the Javadoc do a very bad job at explaining of how to derive the actual parameter name, but after many tries of various case styles, package names etc. I found this to be working:
JAVA_OPTS="-Doracle.jdbc.defaultRowPrefetch=1000" \
./activator -Dconfig.file=conf/xe.conf run
This will make boneCP use a reasonable fetch size without any code change.

Mocking cassandra session object

I an trying to mock the session object of cassandra which is obtained in the actual code in the following way...
session = cluster.connect(keyspace);
What I am looking for is "To execute the statement and return the mock session object"
I have tried the following options
MemberModifier.stub(MemberMatcher.method(Cluster.class, "connect" String.class)).toReturn(session);
PowerMockito.when(cluster.connect(keyspace)).thenReturn(session);
PowerMockito.when(cluster.connect(keyspace)).thenAnswer(new Answer() { public Object answer(InvocationOnMock invocation) { return session; } });
PowerMockito.when(cluster.connect(keyspace)).thenReturn(session);
Session testSession = cassandraService.getCassandraDBConnection();
None of these individually or in combination seem to work.
When the relevant JUnit is executed, the error that I get is
Stack Trace here below...
All host(s) tried for query failed (tried: /<<ip address>>:<<port no>> (com.datastax.driver.core.exceptions.TransportException: [/ip address] Cannot connect))
at com.datastax.driver.core.ControlConnection.reconnectInternal(ControlConnection.java:231)
at com.datastax.driver.core.ControlConnection.connect(ControlConnection.java:77)
at com.datastax.driver.core.Cluster$Manager.init(Cluster.java:1414)
at com.datastax.driver.core.Cluster.init(Cluster.java:162)
at com.datastax.driver.core.Cluster.connectAsync(Cluster.java:333)
at com.datastax.driver.core.Cluster.connect(Cluster.java:283)
at com.capitalone.payments.customerprofile.service.CassandraInteractionService.getCassandraDBConnection(CassandraInteractionService.java:202)
Could somebody guide me here please?
(I have masked ip address and port number in stack trace)
Thanks!
-Sriram
I guess that you want to mock the Java driver session object for testing right ?
In this case, I would recommend:
Use an embedded Cassandra server for unit test, see Achilles Embedded Cassandra or Cassandra Unit
Use the Stubbed Cassandra which simulate CQL requests and responses. This is probably the closest to achieve what you want instead of mocking

Spring Data MongoDB - $eq within $project support

I'm currently writing an aggregation query for MongoDB in my Spring project in which I'm using $project operator. Within this operator I would like to compare two fields in order to return the result as projected "matches" key value. Here's the mongoDB shell equivalent (which works):
{$project:
{matches:
{$eq: ["$lastDate", "$meta.date"]}
}
}
I've read Spring Data MongoDB documentation and found some useful info about ProjectionOperator's 'andExpression' method which uses SpEL. The result Java code of my investigation was:
new ProjectionOperation().andExpression("lastDate == meta.date").as("matches")
Unfortunately I'm receiving exception:
java.lang.IllegalArgumentException: Unsupported Element:
org.springframework.data.mongodb.core.spel.OperatorNode#70c1152a Type: class org.springframework.data.mongodb.core.spel.OperatorNode You probably have a syntax error in your SpEL expression!
As far as I've checked, Spring Data MongoDB handles all Arithmetic operators correctly but cannot handle the comparison ones. Therefore I want to ask is there any other way to create such query with Spring Data MongoDB? Or maybe I don't know something crucial about SpEL?
I resolved this issue by passing JSON aggregate command (created with DBObjects in order to preserve flexibility of the query) to MongoDB, i.e.:
MongoOperations#executeCommand(DBObject command)

Calling HSQLDB IDENTITY function with CallableStatement to get output

I'm trying to use CallableStatements to get the value of IDENTITY() in HSQLDB from Java JDBC.
I can prepareCall fine. The issue is with registerOutputParameter. I get "parameter index out of range" no matter what index I pass in.
I've tried SQL snippets like "{? = CALL IDENTITY()}" with no luck.
Any clues? Am I completely off track in how to invoke HSQLDB function routines from JDBC?
Instead of using IDENTITY(), use getGeneratedKeys() to retrieve any keys generated by the (insert) statement.
Note that you do need to use one of the Statement.execute... or Connection.prepare... methods that will enable this feature.
Gah.
http://sourceforge.net/tracker/index.php?func=detail&aid=3530755&group_id=23316&atid=378134
Output parameters for function invocation is not supported. Use executeQuery and grab the ResultSet.

Resources