Extending SQLServerPreparedStatement in java - java

i'm trying to serialize a prepared statement and store it in a file as object but the object created by my sql driver is of type 'SQLServerPreparedStatement' and is not serializable so i tried to extend it but it's giving me an error when overriding its constructor saying that the constructor is not visible.
any ideas on how to solve this?
PS: my main goal is to store prepared statement objects in file and retrieve them later as prepared statements.
below is my code:
public class WMPreparedStatements extends SQLServerPreparedStatement
{
WMPreparedStatements(SQLServerConnection arg0, String arg1, int arg2,
int arg3) throws SQLServerException {
super(arg0, arg1, arg2, arg3);
// TODO Auto-generated constructor stub
}
}

The JDBC objects (Connection, PreparedStatement, ResultSet etc) are not declared as extending Serializable. The PreparedStatement that you have in your program is the implementation that is provided by your JDBC driver.
Making this PreparedStatement serializable means that you will be able to save it in a file and then restore it from the file. But you should do the same also for the Connection that created it (in your case SQLServerConnection). The JDBC connection is strongly dependent to the underlying network communication. Making a PreparedStatement serializable means that in a scenario you would execute the PreparedStatement inside a transaction, then you would serialize the PreparedStatement without committing and later you would be able to deserialize the PreparedStatement and commit. Such a scenario wouldn't be possible.
Why do you want to serialize the PreparedStatement? Isn't it enough to store the SQL string and the parameters and then read them from the file, open a new connection, create a new PreparedStatement object with the statement that you read, set its parameters and execute it?

well it was impossible to store prepared statement objects in a file and maintain the data in this way, i had to make a workaround.
i stored the statements that i build and that are not set yet (having '?') along with the parameters appended to it separated by a special and unique set of characters, so when i read the file the next time, each query with its parameters are on a separate line, i parse each line to get the values and then store the query in a prepared statement and set its parameters.

Related

Is there any way to retrieve the executed query from java ResultSet?

I created a method called public static ResultSet ExecuteSQLQuery(String myQuery) now at run-time I need to retrieve the executed query from the ResultSet.
I wonder if it is possible to retrieve the executed query from the ResultSet ?
In short: No.
It might be possible to use getStatement from the ResultSet. Some JDBC drivers may expose the query in the statement's toString method, but even if this is the case it should not be relied upon.
You'll have to save the query and keep it around if you want to use it later.
You could create a new type of ResultSet that includes the query and return that:
public class ResultSetWithQuery extends ResultSet {
private String query
...
}
public static ResultSetWithQuery ExecuteSQLQuery(String myQuery);

How to get exact cql from statement using java api from datastax

My code directly executes the bound statement prepared without any exact query. Then how to get the cql it is trying to perform in cassandra database?
For example:
public <T> void save(T entity) {
if (entity != null) {
Statement statement = getEntityMapper(entity).saveQuery(entity);
statement.setConsistencyLevel(consistencyLevelWrite);
mappingManager.getSession().execute(statement);
}
}
I am trying to get something like INSERT INTO "keyspace"."tableName"("column1","column2") VALUES (value1,value2)
My most generic answer is to enable the query logger. It will show executed queries in your application logs.
If you need something more specific and want to manipulate the query string in your own code, you can take inspiration from the implementation: QueryLogger.java. In this particular case, you can get the "generic" query string (with placeholders) by casting to BoundStatement and then invoking .preparedStatement().getQueryString() on it; then inspect the bound statement for the values of the placeholders. As you'll see in the code, QueryLogger handles a lot of corner cases (e.g. truncating large parameters).

How to convert db BLOB column to a byte[] with EntityManager without defining #Entity?

I need to pull a BLOB field out of an Oracle database. I'm using Spring with EntityManager, but I don't want to go through all the effort of defining an #Entity object to represent the table.
I did this something like this ...
String sql = "select * from MY_TABLE where ID = '"+id+"'";
List<Object> resultList = em.createNativeQuery(sql).getResultList();
for (Object o : resultList) {
try {
if (o != null) {
Object[] element = (Object[])o;
byte[] data = (byte[])element[1];
}
... but the problem is the "element[1]" is a "SerialBlobProxy" object, not the array of bytes.
Is there a simple way to convert that "element[1]" into an array of byte[]?
Do Spring JPA allow unwrapping underlying entitymanager connection, then run low-level jdbc resultset and getters. Connection instance you get depends on whether JPA transaction is active or not.
Connection con = em.unwrap(Connection.class);
If you have started EM transaction you get the same connection so be careful not to close,commit,rollback this too soon. You may want to use EM methods finalising transaction. Unwrapping connection without active transaction creates a new instance so caller must close this connection.
There is nothing wrong with using jdbc classes within JPA application, high-level interface may not always suit best all tasks. JPA spec owners know it and lucky to us does not enforce it.
Yes spring does support JDBC template, if you want to bypass using entity manager for your solution. First configure your datasource in spring-config. Make your DAO class extend JdbcDaoSupport (yeah don't forget to inject configured datasource in DAO). With spring JDBC template you could use native queries and also provide custom RowMapper which could be used to map each row to any type. In your case you could read blob as an input stream from database. See following example:
public static class BlobRowMapper implements RowMapper<InputStream> {
#Override
public InputStream mapRow(ResultSet rs, int rowNum) throws SQLException {
return rs.getBinaryStream("blob_column");
}
}
You only have to pass your row mapper to query method. See following snippet:
List<InputStream> rows = getJdbcTemplate().query(query, new Object[] {args}, new BlobRowMapper());
You'll have to read the bytes from input stream.

Hibernate giving org.hibernate.NonUniqueObjectException and saving obsolete object to the database

I have below code in my service class. This code is called twice from 2 different methods as part of a functionality.
//Some code here...
LOG.info("###Inside customer interceptor");
try
{
customerDao.save(customer);
}
catch (final Exception exp)
{
//some code here too...
}
When it is first time called from first method and executed, I can see that there is a select SQL statement printed in tomcat console, but there is no update SQL statement as I expected(May be because of the fact that Hibernate doesn't issue an insert/update immediately).
Immediately When this code block is called again from second method, I see a SQL select statement and then a SQL update statement in tomcat console, and immediately after that I see a big fat org.hibernate.NonUniqueObjectException.
which as I can understand coming because the earlier entity was still attached to session and not committed to DB.
However when I go and see the database I find the values saved in the database were of the object from first call and not the second one as I expected. Is this normal or am I missing something here?
I am using Spring's annotation(#Transactional) driven transaction strategy.
I'd rather use .merge(customer) method or .saveOrUpdate(customer) method to perform this operation.
If you use .merge, you will not get the nonUnique exception as it overwrites the object that is in the session with the one you just passed.
Where as to perform saveOrUpdate, the session should not have the
same instance of the object you are trying to update or else you get this nonUniqueObject exception.
Because you are using spring #Transactional, the transaction should be committed after the complete method has been executed.

HSQL reference custom type in jdbc create array statement

I currently get an SQLException when invoking the createArrayOf(String,Object) of the Connection class. My database is HSQL and the code used to generate the type is as follows:
create type FOO as BIGINT;
The java code I am invoking is as follows:
Connection conn = createConnection();
conn.createArrayOf("MySchema.FOO",data);
This also fails:
Connection conn = createConnection();
conn.createArrayOf("FOO",data);
The resulting output is:
Invalid argument in JDBC call: FOO
My question is how can I bind to a type that exists in a HSQL database, this is not an in memory instance.
User defined types are not currently supported as arguments to this method. You can use "BIGINT". Future versions of HSQLDB may support user defined type arguments.

Categories

Resources