I've got a small problem. I launch my application and after launching a query and comparing rs == null I get error ResultSet is closed.
Here is the code:
error_code = NO_ERROR;
try
{
ArrayList <Harmonogram> al = new ArrayList <Harmonogram> ();
ResultSet rs = stat.executeQuery(myQuery);
if (rs == null)
{
return null;
}else{
Harmonogram harm = new Harmonogram(rs.getLong(1), rs.getInt(2), rs.getInt(3), rs.getInt(4), rs.getLong(5), rs.getString(6));
After this I get a SQLException telling me: ResultSet is closed.
You are using incorrect method of checking whether ResultSet has any data.
Instead of
if ( rs == null )
{
return null;
}
use
if ( ! rs.next( ) )
{
return null;
}
The javadoc for PreparedStatement.executeQuery() says:
"Returns: a ResultSet object that contains the data produced by the query; never null"
The correct way to test for an empty ResultSet is to call ResultSet.hasNext().
Here's how I'd recommend that you write it:
public class HarmonogramDaoImpl implements HarmonogramDao {
private static final String FIND_ALL_SQL = "SELECT * FROM HARMONOGRAM ";
// inject this with either a constructor or setter
private Connection connection;
public List<Harmonogram> findAllHarmonograms() throws SQLException {
List<Harmonogram> harmonograms = new ArrayList<Harmonogram>();
PreparedStatement ps = null;
ResultSet rs = null;
try {
ps = this.connection.prepareStatement(FIND_ALL_SQL);
rs = ps.executeQuery();
while (rs.hasNext()) {
Harmonogram harm = new Harmonogram(rs.getLong(1), rs.getInt(2), rs.getInt(3), rs.getInt(4), rs.getLong(5), rs.getString(6));
harmonograms.add(harm);
}
} finally {
close(rs);
close(ps);
}
return harmonograms;
}
}
There are a few things left for you to do or guess, but this is a good start.
I would do something like
error_code = NO_ERROR;
try
{
ArrayList <Harmonogram> al = new ArrayList <Harmonogram> ();
ResultSet rs = stat.executeQuery(myQuery);
if (rs.next()){
Harmonogram harm = new Harmonogram(rs.getLong(1), rs.getInt(2), rs.getInt(3), rs.getInt(4), rs.getLong(5), rs.getString(6));
}else{
return null;
}
}Catch...
Or even while(rs.next()) if you're trying to loop over the resultSet (get all the records pulled from the database)
Related
The Resultset that is returned from Oracle 11g is processed in Java by using rs.next().
Sometimes (about 1 in 1000), this statement is taking very long to conclude 'false'. Sometimes even several 100 seconds. And this only happens when the result set contains 0 or 1 lines.
But again, a result set with 0 or 1 line are in 999 out of 1000 processed in a few milliseconds.
What could be a reason that rs.next() is sometimes taking so much time?
And although the process takes a lot of time, after a few hundred seconds have passed, the Java code continues without problem.
private List<SomeInfo> getCases(long medewerkerId, long ogeId, OurFilter filter,
ZTCZoekFilter zoekFilter, InterfaceZTC.Sortering sortering) {
List<SomeInfo> foundInfos = new ArrayList<SomeInfo>();
String query = OurImplHelper.createQuery(medewerkerId, ogeId, filter, zoekFilter);
CallableStatement cs = null;
Connection connection = null;
int rowCount = 0;
try {
DataSource ds = null;
String jndiLookup = "java:/dataDS";
Context initCtx = new InitialContext();
ds = (DataSource) initCtx.lookup(jndiLookup);
connection = ds.getConnection();
cs = connection.prepareCall(query);
cs.registerOutParameter(1, oracle.jdbc.OracleTypes.CURSOR);
cs.execute();
ResultSet rs = (ResultSet) cs.getObject(1);
while (rs.next()) {
rowCount++;
SomeInfo caseInfo = new SomeInfo();
caseInfo.setSomecode((String) rs.getObject(1));
....
foundInfos.add(caseInfo);
}
if (cs != null) {
cs.close();
}
if (connection != null) {
connection.close();
}
} catch (Exception e) {
throw new ZakenmagazijnManagerException(e.getMessage());
}
finally {
}
return foundInfos;
}
You do not seem to close things (Connection maybe, cs, rs). Also the variable scope of cs seems too wide from its prepareCall.
Use try-with-resources as in:
try (ResultSet rs = (ResultSet) cs.getObject(1)) {
while (rs.next()) {
rowCount++;
SomeInfo someInfo = new SomeInfo();
someInfo.setSomecode((rs.getString(1));
foundInfo.add(someInfo);
}
return foundInfo;
} // rs is closed.
My style of code:
String query = OurImplHelper.createQuery(medewerkerId, ogeId, filter, zoekFilter);
try {
String jndiLookup = "java:/dataDS";
Context initCtx = new InitialContext();
DataSource ds = (DataSource) initCtx.lookup(jndiLookup);
try (Connection connection = ds.getConnection();
CallableStatement cs = connection.prepareCall(query)) {
cs.registerOutParameter(1, oracle.jdbc.OracleTypes.CURSOR);
cs.execute();
try (ResultSet rs = (ResultSet) cs.getObject(1)) {
List<SomeInfo> foundInfos = new ArrayList<>();
int rowCount = 0;
while (rs.next()) {
rowCount++;
SomeInfo caseInfo = new SomeInfo();
caseInfo.setSomecode((String) rs.getObject(1));
....
foundInfos.add(caseInfo);
}
return foundInfos;
}
}
} catch (Exception e) {
throw new ZakenmagazijnManagerException(e.getMessage());
}
So, I'm getting the error in the title while executing the below process and I really don't know what can be wrong.
What I'm doing is trying to bring some data from a database to create an object and fill and arraylist with several of it's objects, if not found should throw an exceptio
public ArrayList<Caso> buscarCasosPorJuez(String cedula) throws java.sql.SQLException,Exception{
java.sql.ResultSet rs;
String sql;
Caso caso;
ArrayList<Caso> casos = new ArrayList();
sql="SELECT * "+
"FROM tcaso "+
"WHERE CedulaJ='"+cedula+"';";
Conector.getConector().ejecutarSQL(sql);
rs = Conector.getConector().ejecutarSQL(sql,true);
while (rs.next()){
caso = new Caso(
rs.getInt("NumCaso"),
rs.getString("DescripcionCaso"),
rs.getString("EstadoCaso"),
rs.getDate("FechaCreacion").toLocalDate(),
persona.buscarJuezPorCedula(rs.getString("CedulaJ")),
persona.buscarQuerellante(rs.getString("CedulaQ"))
);
casos.add(caso);
}
rs.close();
return casos;
}
Below are the two methods the "New Caso" is calling on the two final lines.
public Juez buscarJuezPorCedula(String cedula) throws java.sql.SQLException,Exception{
Juez juez = null;
java.sql.ResultSet rs;
String sql;
sql = "SELECT Sala,Usuario,Clave,NombreJ,ApellidosJ,TelefonoJ,CedulaJ "+
"FROM tjuez "+
"WHERE CedulaJ='"+cedula+"';";
rs = Conector.getConector().ejecutarSQL(sql,false);
if (rs.next()){
juez = new Juez(
rs.getInt("Sala"),
rs.getString("Usuario"),
rs.getString("Clave"),
rs.getString("NombreJ"),
rs.getString("ApellidosJ"),
rs.getString("TelefonoJ"),
rs.getString("CedulaJ"));
} else {
throw new Exception ("Persona no encontrada intentelo de nuevo.");
}
rs.close();
return juez;
}
public Querellante buscarQuerellante(String cedula) throws java.sql.SQLException,Exception{
Querellante querellante = null;
java.sql.ResultSet rs;
String sql;
sql = "SELECT DireccionQ,NombreQ,ApellidosQ,TelefonoQ,CedulaQ "+
"FROM tquerellante "+
"WHERE CedulaQ='"+cedula+"';";
rs = Conector.getConector().ejecutarSQL(sql,true);
if (rs.next()){
querellante = new Querellante(
rs.getString("DireccionQ"),
rs.getString("NombreQ"),
rs.getString("ApellidosQ"),
rs.getString("TelefonoQ"),
rs.getString("CedulaQ"));
} else {
throw new Exception ("Persona no encontrada intentelo de nuevo.");
}
rs.close();
return querellante;
}
Thanks for all the help you can provide.
I suspect you are closing the Statement object in ejucutarSQL(), which closes all ResultSets derived from it.
You can't actually write all-purpose SQL-executing methods like that, at least not without using CachedRowSet, which costs memory.
You need to restructure this code along more conventional lines, with explicit Connector and Statement objects as local variables so you can close them in reverse order of acquisition.
You should be using PreparedStatements instead of building arguments into SQL strings. If you throw an exception you are also leaking the result set.
For example:
public Querellante buscarQuerellante(String cedula) throws java.sql.SQLException,Exception{
String sql = "SELECT DireccionQ,NombreQ,ApellidosQ,TelefonoQ,CedulaQ "+
"FROM tquerellante "+
"WHERE CedulaQ=?";
try (Connnector conn = ...; // TODO
PreparedStatement ps = conn.prepareStatement(sql);
)
{
ps.setObject(1, cedula);
try (ResultSet rs = ps.execute())
{
if (rs.next()){
return new Querellante(
rs.getString("DireccionQ"),
rs.getString("NombreQ"),
rs.getString("ApellidosQ"),
rs.getString("TelefonoQ"),
rs.getString("CedulaQ"));
} else {
throw new Exception ("Persona no encontrada intentelo de nuevo.");
}
}
}
}
Note that try-with-resources always closes everything allocated, and in the reverse order of acquisition.
I know many questions were asked before for this issue but for this situations I can't find an answer.
This is my code:
private Collection<Coupon> getCouponsMain(Company company, String filters) throws DAOException
{
String sql = null;
if (filters != null)
{
sql = "SELECT couponsystem.coupon.* FROM couponsystem.company_coupon LEFT JOIN couponsystem.coupon ON "
+ "couponsystem.company_coupon.COUPON_ID = couponsystem.coupon.ID WHERE couponsystem.company_coupon.COMP_ID = ? AND ?";
}
else
{
sql = "SELECT couponsystem.coupon.* FROM couponsystem.company_coupon LEFT JOIN couponsystem.coupon ON "
+ "couponsystem.company_coupon.COUPON_ID = couponsystem.coupon.ID WHERE couponsystem.company_coupon.COMP_ID = ?";
}
try (Connection con = pool.OpenConnection(); PreparedStatement preparedStatement = con.prepareStatement(sql);)
{
// query command
preparedStatement.setLong(1, company.getId());
if (filters != null)
{
preparedStatement.setString(2, filters);
}
ResultSet rs = preparedStatement.executeQuery();
if (rs.next())
{
CouponDBDAO couponDao = new CouponDBDAO();
rs.previous();
return couponDao.BuildCoupons(rs);
}
else
{
return null;
}
}
catch (SQLException | NullPointerException e)
{
throw new DAOException("Failed to retrieve data for all coupons" + e.getMessage());
}
}
I think the query itself is not the important issue here but, once I use next() for the ResultSet, I get the error:
java.sql.SQLException: Operation not allowed after ResultSet closed"
This usually happened when using two rs for same statement, this is not the case this time.
Due to many issues with previous method and BuildCoupons(rs) issue, also this part does not work properly for the same reason:
#Override
public Company getCompany(long id) throws DAOException
{
String sql = "SELECT * FROM couponsystem.company WHERE ID = ?";
try (Connection con = pool.OpenConnection(); PreparedStatement preparedStatement = con.prepareStatement(sql);)
{
// query command
preparedStatement.setLong(1, id);
// query execution
ResultSet rs = preparedStatement.executeQuery();
Company comp = new Company();
if (rs.next())
{
//Fill customer object from Customer table
comp.setId(rs.getLong("ID"));
comp.setCompName(rs.getString("COMP_NAME"));
comp.setPassword(rs.getString("PASSWORD"));
comp.setEmail(rs.getString("EMAIL"));
comp.setCoupons(comp.getCoupons());
}
else
{
comp = null;
}
return comp;
}
catch (SQLException e)
{
throw new DAOException("Failed to retrieve data for customer id: " + id);
}
}
BTW - working with MySQL and insert, update and delete queries are working properly so there not issue with the connection to the db
Another update -
Once i replace it to regular statement, it's working but of course i'm losing all the advantages of prepared statement
Like i said i create new code in order to isolate the big program
This is the code:
public class testState
{
public static void main(String[] args) throws SQLException
{
DBDAO pool = DBDAO.getInstance();
String sql = "SELECT ID FROM couponsystem.company WHERE COMP_NAME = ? AND PASSWORD = ?";
String compName = "t";
String password = "t";
pool.CreatePool();
Connection con = pool.OpenConnection();
PreparedStatement preparedStatement = con.prepareStatement(sql);
preparedStatement.setString(1, compName);
preparedStatement.setString(2, password);
preparedStatement.executeQuery();
ResultSet rs = preparedStatement.executeQuery();
System.out.println("rs status: " + rs.isClosed());
if (rs.next())
{
System.out.println("log-in was successfuly performed");
System.out.println(rs.getLong(1));
System.out.println("hjhjh");
}
else
{
System.out.println("-1");
}
rs.close();
preparedStatement.close();
con.close();
pool.CloseConnection();
}
}
Problem was solved,
this is the problem:
sql = "SELECT couponsystem.coupon.* FROM couponsystem.company_coupon LEFT JOIN couponsystem.coupon ON "
+ "couponsystem.company_coupon.COUPON_ID = couponsystem.coupon.ID WHERE couponsystem.company_coupon.COMP_ID = ? AND ?";
the second ? is illegal, but the exception is ResultSet closed and not query issue
the problem is you are trying to go back to the previous record in the result set which is not possible.
learn about scrollable resultset and make it insensitive, once you use this you can go back to the previous record by using rs.previous()
ResultSet.TYPE_SCROLL_INSENSITIVE
Class.forName("org.sqlite.JDBC");
Connection conn =
DriverManager.getConnection("jdbc:sqlite:userdata.db");
Statement stat = conn.createStatement();
ResultSet rs = stat.executeQuery("SELECT * from table WHERE is_query_processed = 0;");
int rowcount = rs.getRow();
System.out.println("Row count = "+rowcount); // output 1
rs.first(); // This statement generates an exception
Why is it so?
The pattern I normally use is as follows:
boolean empty = true;
while( rs.next() ) {
// ResultSet processing here
empty = false;
}
if( empty ) {
// Empty result set
}
Here's a simple method to do it:
public static boolean isResultSetEmpty(ResultSet resultSet) {
return !resultSet.first();
}
Caveats
This moves the cursor to the beginning. But if you just want to test whether it's empty, you probably haven't done anything with it yet anyways.
Alternatively
Use the first() method immediately, before doing any processing.
ResultSet rs = stat.executeQuery("SELECT * from table WHERE is_query_processed = 0;");
if(rs.first()) {
// there's stuff to do
} else {
// rs was empty
}
References
ResultSet (Java Platform SE 6)
You can do this too:
rs.last();
int numberOfRows = rs.getRow();
if(numberOfRows) {
rs.beforeFirst();
while(rs.next()) {
...
}
}
while (results.next())
is used to iterate over a result set.so results.next() will return false if its empty.
Why is execution not entering the
while loop?
If your ResultSet is empty the rs.next() method returns false and the body of the while loop isn't entered regardless to the rownumber (not count) rs.getRow() returns. Colins example works.
Shifting the cursor forth and back to determine the amount of rows is not the normal JDBC practice. The normal JDBC practice is to map the ResultSet to a List of value objects each representing a table row entity and then just use the List methods to determine if there are any rows.
For example:
List<User> users = userDAO.list();
if (users.isEmpty()) {
// It is empty!
if (users.size() == 1) {
// It has only one row!
} else {
// It has more than one row!
}
where the list() method look like as follows:
public List<User> list() throws SQLException {
Connection connection = null;
Statement statement = null;
ResultSet resultSet = null;
List<User> users = new ArrayList<User>();
try {
connection = database.getConnection();
statement = connection.createStatement();
resultSet = statement.executeQuery(SQL_LIST);
while (resultSet.next()) {
User user = new User();
user.setId(resultSet.getLong("id"));
user.setName(resultSet.getString("name"));
// ...
users.add(user);
}
} finally {
if (resultSet != null) try { resultSet.close(); } catch (SQLException logOrIgnore) {}
if (statement != null) try { statement.close(); } catch (SQLException logOrIgnore) {}
if (connection != null) try { connection.close(); } catch (SQLException logOrIgnore) {}
}
return users;
}
Also see this answer for other JDBC examples.
CLOSE_CURSORS_AT_COMMIT
public static final int CLOSE_CURSORS_AT_COMMIT
The constant indicating that ResultSet objects should be closed when the method Connection.commit is called.
Try with this:
ResultSet MyResult = null;
MyResult = Conexion.createStatement().executeQuery("Your Query Here!!!");
MyResult.last();
int NumResut = MyResult.getRow();MyResult.beforeFirst();
//Follow with your other operations....
This manner you'll be able work normally.
This checks if it's empty or not while not skipping the first record
if (rs.first()) {
do {
// ResultSet is not empty, Iterate over it
} while (rs.next());
} else {
// ResultSet is empty
}
May be you can convert your resultset object into String object and check whether is it empty or not.
`if(resultset.toString().isEmpty()){
// containg null result
}
else{
//This conains the result you want
}`
I have problem with return statment >.< I want to store all magazine names into
ArrayList<String> ListNameMagazine = new ArrayList<String>();
I have a DB; in the DB there is a table name_magazine and the data in name_magazine is
Magazine1
Magazine2
Magazine3
Magazine4
This my main:
ShowData Show = new ShowData();
int HowManyMagazine = Show.HowManyMagazine(1); // to make sure there is how many Magazine name in my database
//System.out.print(HowManyMagazine); //i want to make sure the data is out.
String nmeMagazine = null; // this variable for get data from return statement
// i want to store in ListNameMagazine
ArrayList<String> ListNameMagazine = new ArrayList<String>();
for (int numbeer = 0;numbeer <= HowManyMagazine ; numbeer++)
{
//Store in 1 variable String, because if arrayList it's error
nmeMagazine = Show.getResult("Select Name_Magazine from Magazine");
// Store again in array list
ListNameMagazine.add(nmeMagazine);
}
for (String s : ListNameMagazine)
{
System.out.println(s); // show the data
}
This is my return statement:
public String getResult(String sql)
throws SQLException
{
ResultSet rs = st.executeQuery(sql);
ResultSetMetaData resultsetmetadata = rs.getMetaData();
//String just_try = null;
while (rs.next()) {
System.out.println("Result:"+rs.getString(1));
//just_try = rs.getString(1);
//return just_try;
}
return null; //return just_try;
}
The problem is in return statement.
When the comment ( // ) I erase and the last return null; I delete. It become like here:
public String getResult(String sql)
throws SQLException
{
ResultSet rs = st.executeQuery(sql);
ResultSetMetaData resultsetmetadata = rs.getMetaData();
String just_try = null;
while (rs.next()) {
//System.out.println("Result:"+rs.getString(1));
just_try = rs.getString(1);
return just_try;
}
return just_try;
}
When I show the data using this statement.
for (String s : ListNameMagazine)
{
System.out.println(s); // show the data
}
the result only
Magazine4
Magazine4
Magazine4
Magazine4
#.# I have confuse where the miss #.#
but when I show data in return statement like this
public String getResult(String sql)
throws SQLException
{
ResultSet rs = st.executeQuery(sql);
ResultSetMetaData resultsetmetadata = rs.getMetaData();
String just_try = null;
while (rs.next()) {
System.out.println("Result:"+rs.getString(1));
//just_try = rs.getString(1);
//return just_try;
}
return null;
}
The data show what I want. I know I only miss in somewhere but I don't know where that #.#. I hope you guys can found it .THX
Your problem is that return returns only one thing, and it will return immediately and the function will exit! You are retuning the name of a magazine just_try.
while (rs.next()) {
//System.out.println("Result:"+rs.getString(1));
just_try = rs.getString(1);
return just_try;
}
So, you start iterating through rs, and you get the name:
just_try = rs.getString(1);
And then you tell the code to return just_try.
return just_try;
At this point just_try will be returned and the function will exit! I think your problem is that you are expecting the function to keep going, and to keep returning values to the code that calls it, but this is not the way it works.
I suspect what you want to do is something like this:
ArrayList<String> ListNameMagazine;
ListNameMagazine = Show.getResult("Select Name_Magazine from Magazine");
then in the function getResult:
public ArrayList<String> getResult(String sql) throws SQLException {
ResultSet rs = st.executeQuery(sql);
ResultSetMetaData resultsetmetadata = rs.getMetaData();
ArrayList<String> returnArrayList = new ArrayList<String>();
while (rs.next()) {
returnArrayList.add(rs.getString(1));
}
return returnArrayList;
}
xan: Your method returns a String, while you try to return a list.
The signature must be changed to
public List<String> getResult(String sql) throws SQLException;