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);
Related
When I write an accessor for an entity I usually add sync and async versions of the same query. For example:
#Accessor
public interface SourceDataAccessor {
#Query("select * from source_data where data_id = ?")
Result<SourceDataCass> get(UUID dataId);
#Query("select * from source_data where data_id = ?")
ListenableFuture<Result<SourceDataCass>> getAsync(UUID dataId);
}
But when the accessor is instantiated warnings like that appear in the log:
12:32:49,793 WARN com.datastax.driver.core.Cluster:2109 - Re-preparing already prepared query select * from source_data where data_id = ?. Please note that preparing the same query more than once is generally an anti-pattern and will likely affect performance. Consider preparing the statement only once.
May be there is a way to have both sync and async versions of the same query but without re-preparing?
That's an interesting use case.
Currently we don't support it, so the workaround would be to write the accessor with only the async method, and then use getAsync().getUninterruptibly() as the sync version (that's how it's done internally). I agree that it's not very user-friendly, you could use a wrapper class to do it, but that's still an extra step.
One thing we could do pretty easily is cache the prepared statements when we process the methods, so at least it would not prepare twice when a query is repeated within the same interface.
Please open a JIRA ticket if you're interested to see this in the driver. If you feel like fixing it yourself, you can also create a pull request (from a quick look, the only method to change is AccessorMapper#prepare).
You could change the accessor to return a Statement.
#Accessor
public interface SourceDataAccessor {
#Query("select * from source_data where data_id = ?")
Statement get(UUID dataId);
}
and then execute the Statement using
ResultSet rs = session.execute(statement);
or
ResultSetFuture rsf = session.executeAsync(statement);
For mapping the ResultSet to your class you can then use a Mapper
MappingManager mappingManager = new MappingManager(session);
Mapper mapper = mappingManager.mapper(SourceDataCass.class);
Result<SourceDataClass> sourceDataClass = mapper.map(rs);
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).
I'm using spring JdbcTemplate to execute a sql query:
JdbcTemplate template = new JdbcTemplate(ds);
template.execute(sqlInsert); //returns void
How could I get the number of effected rows, as the execute() method returns void?
Call the update method of JdbcTemplate. It will gives you the number of effected rows as return value.
update
public int update(PreparedStatementCreator psc)
throws DataAccessException
Description copied from interface: JdbcOperations
Issue a single SQL update operation (such as
an insert, update or delete statement) using a
PreparedStatementCreator to provide SQL and any required parameters.
A PreparedStatementCreator can either be implemented directly or
configured through a PreparedStatementCreatorFactory.
Specified by:
update in interface JdbcOperations
Parameters:
psc - object that provides SQL and any necessary parameters
Returns:
the number of rows affected
Throws:
DataAccessException - if there is any problem issuing the update
See Also:
PreparedStatementCreatorFactory
You can probably use JdbcTemplate.update() for that case. this will return the number of rows updated or deleted.
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.
I have simple java pojo and it's no entity.
class MyClass {
// fields, getter, setter and etc...
}
Also I have DAO with some function for execute native SQL query (createNativeQuery)
How can mapped result from SQL native query to MyClass without #Entity ?
If the bean field names are the same as the DB table's column names, you can use Spring JDBC's org.springframework.jdbc.core.BeanPropertyRowMapper<T>.
You call org.springframework.jdbc.core.simple.SimpleJdbcOperations.queryForObject(String, RowMapper<T>, Object...)) with the BeanPropertyRowMapper object and it calls all the setters for you, using reflection.
If its JPA, I'd used:
Query query = getEntityManager().createNativeQuery(sql.toString(), MyClass.class);
It works if MyClass is an EntityBean :-(
You can simply issue a query and call the getters/setters in your POJO class.
Pseudo-code:
get connection
ResultSet rs = execute query
if (rs.next()) {
setField1(rs.getString("field1"));
etc....
}
You can use EclipseLink query redirector. The following link explains it. The author has also provided code which is pretty generic and works quite well.
http://onpersistence.blogspot.in/2010/07/eclipselink-jpa-native-constructor.html