requested operation is not supported in result sets - java

I need to display the data returned from a SQL SERVER stored procedure in a Jtable, and yet I have not been able to do it because it gives me the following error: the requested operation is not supported on forwarding-only result sets.
this is the code that I implemented:
try
{
CallableStatement mostararPacientesAusentes = conexionBBDD.getConexionBBDD()
.prepareCall("{call mostararPacientesAusentes()}");
ResultSet tabla = mostararPacientesAusentes.executeQuery();
AbstractTableModel mTN=new ModeloTabla(tabla);
ventanaNotificacion.getTabla().setModel(mTN);
ventanaNotificacion.getTabla().validate();
} catch (SQLException e1) {
JOptionPane.showMessageDialog(null, e1.getMessage(), "BBDD", 2, null);
}
and this is the class that inherits AbstractTableModel
public class ModeloTabla extends AbstractTableModel {
private ResultSet tabla;
private ResultSetMetaData datosBBDD;
public ModeloTabla(ResultSet unResulset)
{
tabla=unResulset;
try
{
datosBBDD=tabla.getMetaData();
}
catch (SQLException e)
{
e.printStackTrace();
}
}
#Override
public Object getValueAt(int rowIndex, int columnIndex) {
try
{
tabla.absolute(rowIndex+1);
return tabla.getObject(columnIndex+1);
}
catch (SQLException e)
{
e.printStackTrace();
return null;
}
}
public String getColumnName(int c)
{
try
{
return datosBBDD.getColumnName(c+1);
}
catch (SQLException e) {
e.printStackTrace();
return null;
}
}
#Override
public int getRowCount() {
try {
tabla.last();
return tabla.getRow();
}
catch (SQLException e) {
e.printStackTrace();
return 0;
}
}
#Override
public int getColumnCount()
{
try
{
return datosBBDD.getColumnCount();
}
catch (SQLException e)
{
e.printStackTrace();
}
return 0;
}
}
The titles of the columns of the table show it in the JTable, but the data does not.
I have already searched unsuccessfully for information to solve the problem.
Thank you very much.

Documentation of ResultSet:
... A default ResultSet object is not updatable and has a cursor that moves forward only. Thus, you can iterate through it only once and only from the first row to the last row. It is possible to produce ResultSet objects that are scrollable and/or updatable. ...
There is a version of prepareCall() that accepts additional arguments to do that, like in:
...prepareCall("{call mostararPacientesAusentes()}",
ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_READ_ONLY);
Please check the documentation for other constants/types.
I am not sure if using a ResultSet to maintain the data is such a good idea - it is probably holding a lot of resources (connection, statement, ...) - IMHO better read the data once and save it in a list or similar structure; releasing the database resources ASAP.

Related

SortedSet not adding new constructed objects from certain sql queried results data

The answer to the following described issue may be as simple as that I am not using SortedSet correctly, but I wouldn't know if that is the case.
void SQLRankGuildsByPoints(final CallbackReturnIntegerStringSortedSet callback)
{
java.sql.Connection cn = null;
try {
cn = DataSource.getConnection();
if(cn != null)
{
PreparedStatement query = cn.prepareStatement("SELECT GuildName, TotalActivityPoints FROM Guilds");
ResultSet result = query.executeQuery();
SortedSet<Pair_IntString> GuildsRanking = new TreeSet(new ComparatorGuildsRanking());
while(result.next())
{
int resultInt = result.getInt("TotalActivityPoints");
String resultString = result.getString("GuildName");
GuildsRanking.add(new Pair_IntString(resultInt, resultString));
}
Bukkit.getScheduler().runTask(MainClassAccess, new Runnable() { //Callback to main thread
#Override
public void run() {
callback.onDone(GuildsRanking);
}
});
}
} catch (SQLException e) {
System.err.print(e);
} finally {
try {
cn.close();
} catch (SQLException e) {
System.err.print(e);
}
}
}
All 8 results from the Guilds table are present in "result" ResultSet.
GuildsRanking.add() isn't adding the new custom Pair_IntString object constructed with the query results, specifically for guilds "test" and "lilo" in Guilds table.
SQLRankGuildsByPoints method finishes it's execution, calling back the GuildsRanking SortedSet without 2 of the iterated results.
This behaviour is unintended and I can't find an explanation for it.
The comparator used for TreeSet:
public class ComparatorGuildsRanking implements Comparator<Pair_IntString> {
#Override
public int compare(Pair_IntString intStr1, Pair_IntString intStr2) {
return intStr2.integer.compareTo(intStr1.integer);
}
}
Custom Pair_IntString class:
public class Pair_IntString {
public Integer integer;
public String string;
Pair_IntString(Integer i, String s)
{
integer = i;
string = s;
}
}
No error messages with the skipped add iterations.

H2 1.4.199 database getGeneratedKeys() returns key generated by another insert transaction OR Future objects are mixed up

I am using Java 1.8 and H2 1.4.199.
I have a method insertRecord(DATA_OBJECT) which inserts single row into table, and then returns the generated ID for this row. It instantiates a Task object and submit it onto SingleThreadExecutorService one-by-one, and the generated ID is retrieved from Future object. Most of the time it works just fine. However, sometimes a situation like this happens:
Row 10 insert is submitted to ExecutorService
Row 11 insert is meant to be waiting in front of "synchronized" block to be submitted to ExecutorService
Row 10 is being inserted by code, and Future returns generated ID = 11
Row 11 is being inserted by code, and Future returns generated ID = 11
I have no working and reproducible example, because it is a very rare situation, but it happens.
No exceptions thrown and I have no idea how this could happen.
Below is the example of code:
private static final ExecutorService singleExecutor = Executors.newSingleThreadExecutor();
private static String insertRecord(DATA_OBJECT dataObject) {
Future<String> future;
synchronized (singleExecutor) {
future = singleExecutor.submit(new Task(dataObject));
}
try {
return future.get();
} catch (InterruptedException ex) {
Logger.getLogger(CLASS_NAME.class.getName()).log(Level.SEVERE, null, ex);
} catch (ExecutionException ex) {
Logger.getLogger(CLASS_NAME.class.getName()).log(Level.SEVERE, null, ex);
}
}
private class Task implements Callable<String> {
private DATA_OBJECT dataObject;
public Task(DATA_OBJECT dataObject) {
this.dataObject = dataObject;
}
#Override
public String call() {
try {
return execute(dataObject);
} catch (SQLException ex) {
Logger.getLogger(CLASS_NAME.class.getName()).log(Level.SEVERE, null, ex);
}
return null;
}
}
private static String execute(DATA_OBJECT dataObject) {
Connection conn = Database.getTransactedConnection();
String lastId = null;
boolean success = false;
try (
PreparedStatement statement =
conn.prepareStatement(
"insert into TABLE (COLUMN_NAMES) values (VALUES)",
Statement.RETURN_GENERATED_KEYS
)
) {
statement.setString(1, dataObject.STRING_1);
statement.setString(N, dataObject.STRING_N);
success = statement.executeUpdate() == 1;
if (success) {
try (ResultSet generatedKeys = statement.getGeneratedKeys()) {
if (generatedKeys.next()) {
lastID = generatedKeys.getString(1);
}
}
}
} finally {
if (success)
conn.commit();
else
conn.rollback();
Database.releaseConnection(conn);
}
return lastId;
}
I am trying to find a way to avoid 100% of these events because the consequences are devastating. How can I do this?
What could be the problem leading to the return of the identifier from the future?

Java - Design Pattern for repeating sql tasks

I have different methods, which queries different data from a database, but the main structure of every method is the same. To reduce the code, I want to shrink that but I don't know how. I have tried interfaces but the return statement cannot called from an inner class. (It should be typesafe!)
Structure:
public <special type> getXYdata(some parameters) {
try (Connection connection = mDataSource.getConnection();
Statement statement = connection.createStatement();
ResultSet results = statement.executeQuery(... special query ...)
) {
// Handle ResultsSet and return object of a special type.
} catch (SQLTimeoutException e) {
throw new ContentManagerException("Query took to long or connection timed out", e);
} catch (SQLException e) {
throw new ContentManagerException("Query or parsing its results failed", e);
}
}
Idea:
private interface QHandler<T> {
String getQuery();
T handleResultSet(ResultSet set) throws SQLException;
}
And then:
private void executeQuery(QHandler handler) throws ContentManagerException {
try (Connection connection = mDataSource.getConnection();
Statement statement = connection.createStatement();
ResultSet results = statement.executeQuery(handler.getQuery())
) {
handler.handleResultSet(results);
} catch (SQLTimeoutException e) {
throw new ContentManagerException("Query took to long or connection timed out", e);
} catch (SQLException e) {
throw new ContentManagerException("Query or parsing its results failed", e);
}
}
But if I call this private method in one of my data mathods, I cannot return an object from the handleResultSet() methods, because the return statement will affect this interface method. Is there an option, to tell the execiteQuery() method which return type the handler has?
Attention: It has to be type safe, no casting if possible!
Your method should not use a raw QHandler type, and should be generic:
private <T> T executeQuery(QHandler<T> handler) throws ContentManagerException {
try (Connection connection = mDataSource.getConnection();
Statement statement = connection.createStatement();
ResultSet results = statement.executeQuery(handler.getQuery())
) {
return handler.handleResultSet(results);
} catch (SQLTimeoutException e) {
throw new ContentManagerException("Query took to long or connection timed out", e);
} catch (SQLException e) {
throw new ContentManagerException("Query or parsing its results failed", e);
}
}
Note that you're trying to reinvent Spring's JdbcTemplate. You might consider using it instead of reinventing it.
Maybe you are open for alternative solutions. If you are using Java 8, you can do somehting like this:
Interface MyHandler {
<T> T handle(Connection c);
}
class MyHelperClass {
public <T> T withConnection(MyHandler handler) {
try {
Connection connection = mDataSource.getConnection();
return handler.handle(connection);
} catch (...) {
...
} finally {
...
}
}
}
Usage:
Result r = myHelperObject.withConnection(con -> {
ResultSet results = connection.createStatement().executeQuery(query)
return new Result(..)
});
This way you can use lambda expressions so you do not need to implement various new classes for your handler interface.

how to get a ResultSet from an outside java class

I have a ResultSet object
ResultSet theInfo = stmt.executeQuery(sqlQuery);
but I want to have a function that can be called from another java class
public Vector loadStuff(){
try {
while (theInfo.next()){
aVector.addElement(new String(theInfo.getString("aColumn"))); // puts results into vectors
}
} catch (SQLException e) {
e.printStackTrace();
}
return aVector;
}
I'm not entirely sure how to go about this. I want to some how call a void method that returns a populated vector. is this possible?
Suppose you have a class Demo and it has method getVector follow the given approach.
class Demo {
public Vector getVector(ResultSet theInfo) {
if(theInfo==null){
throw new IllegalArgumentException("ResultSet is null");
}
Vector aVector = new Vector();
try {
while (theInfo.next()) {
aVector.addElement(new String(theInfo.getString("aColumn")));
}
} catch (SQLException e) {
e.printStackTrace();
}
return aVector;
}
}
Now call the getVector after the getting the ResultSet.
ResultSet theInfo = stmt.executeQuery(sqlQuery);
Demo demo =new Demo();
Vector vector=demo.getVetor(theInfo );

Implementation of SQL Iterators

Does anyone know good source where I can find about implementation of SQL iterator/Operator in java and any other languages?
I'm going to go with Elijah's interpretation, that Nimesh actually meant, "Is it possible to make a wrapper Iterable for a ResultSet. Here's something I whipped up. It's obviously not yet production-ready, but it definitely gives the idea. Since there is no standard (as far as I know) ResultSetRow, it returns an Object[] for each row.
There are some significant issues with this concept, not least that Iterator is not allowed to throw, so SQLExceptions are handled as best possible "on-site". Also, ResultSet is a very complex and featureful beast (see for instance the overloaded methods for every type). This complexity could be partially taken advantage of but isn't. For instance, there could be methods like getIntIterable(ResultSet rs) which returns a Iterable<int[]>. The method could check the getColumnTypes of the ResultSetMetadata object. That way, it could throw (if for instance not all columns are ints) before creating the Iterable, the methods of which can not throw.
public static class ResultSetIterable implements Iterable<Object[]>
{
private ResultSet rs;
private int columnCount;
public ResultSetIterable(ResultSet rs) throws SQLException
{
this.rs = rs;
columnCount = rs.getMetaData().getColumnCount();
}
public Iterator<Object[]> iterator()
{
return new Iterator<Object[]>()
{
private boolean moreRows;
{
try
{
moreRows = rs.first();
}
catch(SQLException e)
{
moreRows = false;
}
}
public boolean hasNext()
{
boolean knownClosed = false;
try
{
knownClosed = rs.isClosed();
}
catch(Throwable e)
{
// Ignore possible SQLException or AbstractMethodError or...
}
return !knownClosed && moreRows;
}
public Object[] next()
{
Object[] curRow = new Object[columnCount];
for(int i = 1; i <= columnCount; i++)
{
try
{
curRow[i - 1] = rs.getObject(i);
}
catch(SQLException e)
{
curRow[i - 1] = null;
}
}
try
{
moreRows = rs.next();
}
catch(SQLException e)
{
moreRows = false;
}
return curRow;
}
public void remove()
{
try
{
rs.previous();
rs.deleteRow();
}
catch(SQLException e)
{
throw new UnsupportedOperationException("ResultSetIterable does not support remove for this ResultSet type.");
}
}
};
}
}

Categories