my problem is not how to retreive data from resultset but it's about a resultset that it's not like we used to know
i will explain :
My database is on an remote server, connection via ssh established and everything works perfectly
but the problem is that i'm using resultset to get result from a "queryString" variable that i defined which get the query as a string from the front-end as a request and then , this query will be executed with the method i defined
and since we don't know beforehand from which table we re going to read data and how many columns are we going to retrieve , i didn't know how to make this method works on every recieve query
below is my code snippet :
#Override
public SqlQuery exeuteReceivedQuery(String queryString) throws SQLException {
ConnectToDataBase();
Statement st = (Statement) conn.createStatement();
ResultSet rs = st.executeQuery(queryString);
SqlQuery result = null;
while(rs.next()) {
result = new SqlQuery();
result.getQueryResult();
}
return result;
}
// controller
#GetMapping(value = "/{queryString}",produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<SqlQuery> getResults(#PathVariable("queryString") String queryString) throws SQLException {
SqlQuery cmd = sqlService.exeuteReceivedQuery(queryString);
return new ResponseEntity<>(cmd, HttpStatus.OK);
}
Does anyone of you have an idea on how to do this ?
Thanks in advance :)
You can access the ResultSet's metadata
rs.getMetaData().getColumnCount();
and then
rs.getMetaData().getColumnName(i);
You can obtain from the metadata columns, names, data types etc. all you need to extract the results
Related
I have in one java class a method which SELECT one column from a table from my database, and that column is an INT type in the database, and then I selected items from that column, put in a List<Long> and method returns this List. Here is the method:
public List<Long> vratiSveSifreRacuna() throws SQLException {
String sqlVratiSifruRacuna = "SELECT RacunID FROM racun";
Statement stat = konekcija.createStatement();
ResultSet rs = stat.executeQuery(sqlVratiSifruRacuna);
Long racunID = 0L;
List<Long> sifre = new ArrayList<>();
while (rs.next()){
//racunID = rs.getLong("RacunID");
sifre.add(new Long(rs.getInt("RacunID")));
}
return sifre;
}
The problem is, when I start debuging line by line, on this line:
ResultSet rs = stat.executeQuery(sqlVratiSifruRacuna);
it crashes, it jumps on exception. It cannot execute this query and I don't know why, because similar queries it execute well. Do you know what could be the problem? Is the problem maybe because the column I want to select is autoincrement and primary key? I don't know...
Your public (assuming static) method needs the connection object passed into it as an argument as it is not available in the local scope:
public static List<Long> vratiSveSifreRacuna(Connection konekcija) throws SQLException {
String sqlVratiSifruRacuna = "SELECT RacunID FROM racun";
Statement stat = konekcija.createStatement();
ResultSet rs = stat.executeQuery(sqlVratiSifruRacuna);
Otherwise include connection inside local context:
public static List<Long> vratiSveSifreRacuna(String url, String username, String password) throws SQLException {
Connection konekcija = DriverManager.getConnection(url, username, password);
String sqlVratiSifruRacuna = "SELECT RacunID FROM racun";
Statement stat = konekcija.createStatement();
ResultSet rs = stat.executeQuery(sqlVratiSifruRacuna);
I solved the problem finally so I wanted to share the solution. The problem was actually stupid, I accidentally put the code line which makes connection with database below the line where I called this method. So there where the method was called, sql query was actually empty, so it alerts error nullPointerException.
I'm trying to get some data from Oracle 11.2 using java and jdbc driver.
My goal is to get data from database using CallableStatement, but with no luck - I'm not able to put table name as parameter. I would like to have configurable table name in query. However, it would be good to keep it sanitized.
Here is an example..
public void getData() throws SQLException {
Connection conn = Config.getSQLConnection();
String query = "SELECT * FROM ?";
PreparedStatement st = conn.prepareStatement(query);
st.setString(1, Config.DATATABLE_NAME);
ResultSet rs = st.executeQuery();
if (rs.next()) {
System.out.println("SUCCESS");
System.out.println("ID:" + rs.getString("ID"));
} else {
System.out.println("FAILURE");
}
}
Is this the way it should work? Or am I missing something, or misused it?
A CallableStatement is used to make call to stored procedures.
From javadoc:
The interface used to execute SQL stored procedures
Use a PreparedStament instead for a normal select.
As an additional note don't pass the name of the table as parameter.
Create the query using concatenation.
Instead of
String query = "SELECT * FROM ?";
use
String query = "SELECT * FROM " + Config.DATATABLE_NAME;
You should use PreparedStatement instead of CallableStatement.
CallableStatement is an interface which is used to call stored procedures.
So say a column is named Names I want to get a ArrayList of every variable inside of this column. Example:
Names
Test
Test1
Test3
River
World
Etc
I want to get all of that into an array list. Thanks for the help!
You're not giving much information in your question (e.g. what is the table you'd like to query), so here's a somewhat generic solution:
public List<String> retrieveAllColumnValues(Connection connection) throws SQLException {
String query = "SELECT Names FROM MyTable";
List<String> values = new ArrayList<>();
try (Statement stmt = connection.createStatement()) {
ResultSet rs = stmt.executeQuery(query);
while (rs.next()) {
values.add(rs.getString("Names"));
}
rs.close();
}
return values;
}
Getting data from the database through JDBC roughly consist of the following parts:
You have a Connection which you use for creating SQL Statements
When you execute the Statement, you get a ResultSet, which contains the values returned by your query
You iterate through the ResultSet and do what you need to with the values
I am using Oracle JDBC Driver ojdbc6.jar. When executing a PreparedStatement the ResultSet is returned. However when trying to get details back of what has been saved, I am unable to get this and it throws an Exception.
Below is the code:
public Processor {
private Connection connection;
public Processor() throws Exception {
connection = DriverManager.getConnection(url, username, password);
}
public int saveData(String name) throws Exception {
PreparedStatement preparedStatement = connection.prepareStatement(name);
preparedStatement.setString(1, name);
ResultSet resultSet = preparedStatement.executeQuery();
resultSet.next();
String row = resultSet.getString("NAME");
return resultSet.getRow();
}
public static void main(String[] args) throws Exception {
Processor processor = new Processor();
int row = processor.saveData(new String("INSERT INTO NAMES (name) VALUES (nameTable)"));
}
}
The url, username and password are setup but not shown in the code. I can connect to the Oracle database and persist the data. However, the problem arises when calling resultSet.getString("NAME"). The following Exception is shown:
ORA-009900: invalid SQL statement
java.sql.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:447)
When executing the following code:
ResultSet resultSet = connection.createStatement().executeQuery("SELECT NAME FROM NAMES"));
resultSet.next();
String name = resultSet.getString("NAME");
This works. I have also executed in the SQL describe NAMES and the name attribute is displayed as NAME.
The issue is something to do with the PreparedStatement object returning the ResultSet data.
Any ideas?
EDIT:
ORA-00900: invalid SQL statement
java.sql.SQLSyntaxErrorException
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:447)
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:389)
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:382)
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:675)
at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:513)
at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:227)
at oracle.jdbc.driver.T4C8Odscrarr.doODNY(T48COdscrarr.java:98)
at oracle.jdbc.driver.T4CPreparedStatement.doDescribe(T4CPreparedStatement.java:818)
at oracle.jdbc.driver.OracleStatement.getColumnIndex(OracleResultSetImpl.java:3711)
at oracle.jdbc.driver.OracleResultSetImpl.findColumn(OracleResultSetImpl.java:2799)
at oracle.jdbc.driver.OracleResultSet.getString(OracleResultSet.java:498)
at com.example.ProcessorTest.testExecuteInsert(ProcessorTest.java:14)
Your saveData method is the cause because an INSERT does not produce a ResultSet, so executeQuery will produce an error, as there will be no ResultSet.
Also you should only use connection.prepareCall(String) for executing stored procedures, not for other types of statements. For a prepared statement you should use connection.prepareStatement(String).
Change your code to:
public int saveData(String name) throws Exception {
PreparedStatement preparedStatement = connection.prepareStatement(name);
preparedStatement.setString(1, name);
return preparedStatement.executeUpdate();
}
BTW: I hope you are aware that this method uses the parameter name both for the query and as the parameter for the query (which really does not make a lot of sense).
And finally, the new String(...) you do in your main is totally unnecessary.
First of all this line of code
int row = processor.saveData(new String("INSERT INTO NAMES (name) VALUES (nameTable)"));
As you have specified that the method saveData() takes argument as String so there is no need of any new String(...) here and moreover you are using PreparedStatement so you can use parameterized query something like this
int row = processor.saveData("INSERT INTO NAMES (name) VALUES (?)");
Then you can use this statement in saveData()
preparedStatement.setString(1, "name");
Finally you are updating the table not quering it so change this
preparedStatement.executeQuery();
to
return preparedStatement.executeUpdate();
One more thing you should be very specific about your method name. You should always name a method based on what it is going to do. Like saveData() here must be used only for saving data not querying the data as you were trying to do by using the ResultSet. If you want to retrieve the data then use some other method.
If I'm not mistaken, a preparedStatement is destroyed from cache once a connection is closed. At the moment my app is setup so that I have a function to get POJO objects from the database based on the single POJO object passed in. I then have another function to get id's of ALL objects in that table for cases where I need a list, and then in the while loop of that function I get the entire objects one at a time.
However doing this doesn't take advantage of cached queries right? So what is the best way to have a generic getter SQL function that can make use of cached preparedstatements if it is a list of items or a single item? In PHP I can do this easily by checking if the passed in param is an array or not, but Java requires you to define the param object.
So for example, let's say users, here is what I currently have:
//Get user object
public User getUser(User user) throws SQLException {
Connection connection = connectionWrapper.getConnection();
String query = "SELECT firstName, lastName FROM users WHERE userId = ?";
PreparedStatement statement = connection.prepareStatement(query);
statement.setInt(1, user.getUserId());
ResultSet rs = statement.executeQuery();
if (rs.next()) {
//Get database details and set into object
}
rs.close();
statement.close();
connection.close();
}
//Get all users
public List<User> getAllUsers() throws SQLException {
List<User> userArr = new ArrayList<User>();
Connection connection = connectionWrapper.getConnection();
String query = "SELECT userId FROM users";
PreparedStatement statement = connection.prepareStatement(query);
ResultSet rs = statement.executeQuery();
while (rs.next()) {
int id = rs.getInt("userId");
User user = new User(id);
getUser(user);
userArr.add(user);
}
rs.close();
statement.close();
connection.close();
return userArr;
}
It would be nice to be able for the getUser function to handle both an individual object case like above and an array case where an array of user objects (with userId's set) are passed in and it loops through the array to get all objects before closing the connection. Is there a non-messy way to do this or should I just pass a User array to the getUser function in all cases, even if it's just one?
If what you're after is performance, then executing 5 queries to find 5 users given an array of 5 IDs is not really the best solution. You'd better execute a single query that loads all the users at once, using
select firstName, lastName FROM users WHERE userId in (?, ?, ?, ?, ?)
Similarly, your getAllUsers() method is extremely inefficient. It should execute a single query, instead of executing a query to get all the IDs, and then a query for every ID found.