How to cast A ResultSet object in to Comparable object - java

I am writing a generic Java code and i want to add integers to a min Heap which will be stored in a mysql database. For that i have written below code,
public void addElement(Comparable value) {
sql = "INSERT INTO testHeap VALUES("+size+","+(int)value+ ") ";
try {
stmt.executeUpdate(sql);
size++;
} catch (SQLException ex) {
Logger.getLogger(HeapMySql.class.getName()).log(Level.SEVERE, null, ex);
}
if(size == 0) throw new IllegalStateException("Shape error");
int index = size - 1;
while(size != 0) {
sql = "SELECT value FROM testHeap WHERE indexnum ="+index;
T val;
try {
val = (T)stmt.executeQuery(sql);
if(myParent(index).compareTo(val) <= 0) break;
swap(parent(index), index);
index = parent(index);
} catch (SQLException ex) {
Logger.getLogger(HeapMySql.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
This returns below exception in runtime
Exception in thread "main" java.lang.ClassCastException: com.mysql.jdbc.JDBC4ResultSet cannot be cast to java.lang.Comparable
at Lab03.HeapMySql.addElement(HeapMySql.java:140)
I wan to know how to do this "val = (T)stmt.executeQuery(sql)" properly :)

You need to specify a column in the result set (even though there's only one)
val = (T)new Integer(stmt.executeQuery(sql).getInt(1));
As you commented below, you need an active row in your result set.
You also need to close it after you're done or you'll run out of database cursors. Reading past the last row (using rs.next) will automatically close it, so I use a "while" instead of an "if".
ResultSet rs = stmt.executeQuery(sql);
while (rs.next()) {
val = (T)new Integer(rs.getInt(1)))
}

The ResultSet has all results as an Object in an array, it's not the result itself! You have to cast every single one to the type it is. Furthermore the ResultSet can be used to make easy changes back to the database, too. So you didn't get the concept of jdbc at all ^^ You should read a few tutorials how to work with jdbc in general.
For further help please make your question better understandable. We can't know which line is 140 (from the error), i assume:
if(myParent(index).compareTo(val) <= 0) break;

Related

Return integer for the last row in MYSQL using JDBC

I'm new to working with JDBC commands. I have a database in MYSQL and each entry gets an ID. As initially created the ID was just a static variable that I iterated when the constructor runs. This was okay until I started deleting entries or running the program a second time. Then I start getting collisions. I need a way to return the highest row in the table and assign it to an integer that I can iterate.
The QuerySELECT MAX(ID) FROM table seems to get the value that I'm looking for. But I'm not sure of the syntax to get that value into an integer so I can return it.
public int getHighestRow() {
PreparedStatement ps;
int highestID = 0;
try {
ps = getSQLDB().prepareStatement("SELECT MAX(studentID) FROM student");
ps.execute();
} catch (SQLException e){
Logger.getLogger(Undergraduate.class.getName()).log(Level.SEVERE, null, e);
}
if (highestID > 0) return highestID;
else return 0;
I have a feeling this is very simple, but I wasn't able to find an existing answer. Or is there a more elegant way to do this in general?
SQL of different providers solve the retrieval of automatic generated keys differently. JDBC provides a standard solution.
Better use this JDBC solution, as it prevents mixing up those keys when insertions are done at the same time.
try (PreparedStatement ps = getSQLDB().prepareStatement(
"INSERT INTO student(....) VALUES(?, ..., ?)",
Statement.RETURN_GENERATED_KEYS)) { // Without StudentId
ps.setString(1, name);
...
ps.executeUpdate();
try (ResultSet rsKeys = ps.getGeneratedKeys()) {
if (rsKeys.next()) { // Only one record inserted
int studentId = rsKeys.getInt(1); // One key generated
}
}
} catch (SQLException e){
Logger.getLogger(Undergraduate.class.getName()).log(Level.SEVERE, null, e);
}
The mechanism with try(...). try-with-resources, ensures that close is called automatically.

Java, double returning function, what to return on failure?

I am moving from PHP to Java and I'm a little struggled.
I have this method like this that I use to get some data from MySQL database and I would like to treat the failure if no data got from database.
public double getRate() {
double ret;
try {
// do a select query
PreparedStatement stmt = conn.prepareStatement("SELECT `rate` FROM `rates` LIMIT 1");
ResultSet rs = stmt.executeQuery();
// get result
rs.absolute(1);
ret = rs.getDouble(1);
// close the resources
rs.close();
stmt.close();
}
// this catches only the SQL errors (if I am right)
catch (SQLException ex) {
ex.printStackTrace();
}
// THIS IS WRONG BECAUSE "variable ret might not have been initialized"
return ret;
}
In PHP we can return whatever in case of failure like this:
<?php
public function getRate() {
$ret = db::getOne("SELECT `rate` FROM `rates` LIMIT 1");
if ($ret) {
return $ret; // row has been found, so we return it
} else {
return false; // row hasn't been found, so we return false --> THIS is what I need to do in Java
}
}
?>
So how to treat a failure in Java methods/functions where I have nothing to return?
You have several options:
throw an exception, and catch this by the code which calls the method. This works well, is a nice way to handle it. But requires a lot of additional try-catch statements
Return -1 on error. This is also a very common way to do if you work with natural numbers only
always return a result object, which contains a the output and a success/error status
Use the Double Class instead, and return null on fail
In Java, you can't return double from one place and boolean from another. What you could do is, initialize your Double (wrapper of double primitive) value like:
Double ret = null;
And if there are no rows or any SQLException, you would return this value back to caller. In called method you could do something like:
Double rate = getRate();
if (rate == null) {
//no row found
} else {
//i have the row. continue with business logic
}
You could make your method return an object of the double wrapper class Double. Then you could return a null pointer in case of some failure.
public Double getRate() {
...
if(ok)
return new Double(ret);
else
return null;
}
Initialize your double variable with a control value. If it is not changed when exiting the method, then something went wrong.
The control value can be something you do not expect to get from the query, so for rates it could be a negative number, say -1 since rates can't be negative.
double ret=-1.00d;
I am adding a sample code so you can understand how to handle such scenarios.
If your default value does not changes,it means there was nothing that matched your query.
public double methodName(int arg)
{
double risk=0.0;
String query = null;
PreparedStatement stm = null;
ResultSet r = null;
Connection con=null;
try{
con=ConnectionDB.getConnection();
if(con!=null)
{
query="select risk from table where year="+arg;
stm = con.prepareStatement(query);
r = stm.executeQuery();
if(r.next())
{
risk=r.getDouble(1);
}
}
}catch(Exception e)
{
e.printStackTrace();
}
finally{
try {
if (r != null) {
r.close();
}
if (stm != null) {
stm.close();
}
if(con!=null)
{
con.close();
}
} catch (Exception e) {
System.out.println("" + e);
}
}
return risk;
}
You could return an OptionalDouble, which makes it obvious to the caller that they need to handle the case of the result not being found:
try {
// get ret
return OptionalDouble.of(ret);
} catch (SQLException ex) {
return OptionalDouble.empty();
}
In your Java example, when you talk about a "failure", you are talking about an unexpected error (e.g. a SQL Exception, a non-expected error in the DB access).
Nevertheless, in your PHP example, when you talk about a "failure", you are talking about a normal scenario (No data in database).
So, both examples are quite different.
In my opinion, if I get an unexpected sitution, I wouldn't return any value, I'd throw an exception. I usually return null, -1 and this kind of values in normal and expected scenarios where there isn't data to return.

Java -> Mysql: get INT doesnt work?

In my DB theres a field named 'failcounter' and its an int.
Which query i have to use to receive the int?
i tried with:
SELECT `failcounter` FROM `randomstuff`
and tried to receive the int with:
if(zrs.next()){
return zrs.getInt(1);
}else{
return -99;
}
but im not able to get the int.
Whats wrong? =)
Here is the whole method, maybe theres something wrong:
public static int getFailCounter() throws Exception {
try {
// This will load the MySQL driver, each DB has its own driver
Class.forName("com.mysql.jdbc.Driver");
// Setup the connection with the DB
connect = DriverManager.getConnection(""+MyBot.mysqlDbPath+"",""+MyBot.mysqlDbUsername+"",""+MyBot.mysqlDbPassword+"");
PreparedStatement zpst=null;
ResultSet zrs=null;
zpst=connect.prepareStatement("SELECT `failcounter` FROM `randomstuff`");
zrs=zpst.executeQuery();
if(zrs.next()){
return zrs.getInt(1);
}else{
return -99;
}
}catch (Exception e) {
throw e;
} finally {
close();
}
}
From your comment I always get -99
It means that ,
if(zrs.next()){
return zrs.getInt(1);
}
doesnt gets executed . Also understand the differences using if(zrs.next()) and while(zrs.next())
You usually use "while" as you want to loop through all the data in the result set. You use "if" when the query returns one row by definition
So in your case the ResultSet must be null or the column index might be wrong . so check for the Data in the table first
Hope this helps !
Try you this.
ResultSet res = st.executeQuery("SELECT * FROM event");
while (res.next())
{
int id = res.getInt("id");
String msg = res.getString("msg");
System.out.println(id + "\t" + msg);
}
And follow more read [How to connect with MySQL database using Java
Read more: http://mrbool.com/how-to-connect-with-mysql-database-using-java/25440#ixzz30N93JAkm]1
Best of Luck!

Java: Problem with return value

I know it may seem like an easy to solve problem, but I can't find my fault in this piece of code. I'm returning int and Eclipse is telling me that 'This method must return a result of type int'.
public static int getLastId(int table) {
Connection connection = null;
String url = "jdbc:postgresql://someServer:port/someDB";
try {
//Verbindung herstellen
connection = DriverManager.getConnection(url, "someUser",
"somePassword");
} catch (SQLException e1) {
//fehlerhafte Verbindung
// TODO Auto-generated catch block
e1.printStackTrace();
}
try {
//0 - source ; 1 - destination Table
if(table == 0){
Statement stmt = connection.createStatement();
ResultSet lastId;
lastId = stmt.executeQuery("SELECT index FROM table0 ORDER BY someIndex DESC LIMIT 1");
String theLastId0 = "";
while(lastId.next())
{
//System.out.print(lastId.getString("index"));
theLastId0 = lastId.getString("index");
}
lastId.close();
stmt.close();
connection.close();
int letzteId0 = Integer.parseInt(theLastId0);
return letzteId0;
}else if(table == 1){
Statement stmt = connection.createStatement();
ResultSet lastId;
lastId = stmt.executeQuery("SELECT index FROM table1 ORDER BY someIndexDESC LIMIT 1");
String theLastId1 = "";
while(lastId.next())
{
//System.out.print(lastId.getString("index"));
theLastId1 = lastId.getString("index");
}
lastId.close();
stmt.close();
connection.close();
int letzteId1 = Integer.parseInt(theLastId1);
return letzteId1;
}
}
catch (SQLException e) {
System.out.println("Connection Failed! Check output console");
e.printStackTrace();
return -1;
}
}
What happens if table != 0 and table != 1? Then your method doesn't return anything. So either add an else statement to your if or just a regular return, returning a dummy value like -1.
Even if you, the programmer, know that this case will never be executed, the compiler doesn't know that so you gotta make it happy anyways. Plus nasty things can be done using reflection so it's never a good idea to assume the input to your methods are valid.
This method must Always return an int.
You must add the following else statement
else {
return 0;
}
after the else if because in your version you don't return anything if your if AND your else if evaluates to false.
If table != 0 or 1, then your code does not return anything. Just add return 0; at the very end or whatever the appropriate behavior is, then you should be fine.
For future reference, your methods must return a value in every condition if a return type is specified. If there is a situation where nothing is returned, then the code is faulty. Hope it helps!

exhausted resultset error when i get the name of the columns

i'm trying to get the type and the name of the result and when enter in the loop, excuting somo instructions about the metadata the resulset.next changed from true to false, and give the error java.sql.SqlExcepcion exhausted resultset. Any ideas? i really dont know how solved it because i read the post with the solution of this problem and validate if the resultset it's null before begin the loop. I'm called this method with a scheduler of quartz. I'm using this in a j2ee aplication and the example it's this
try
{
InitialContext ctx = new InitialContext();
WrapperDataSource wrapperDataSource = (WrapperDataSource)ctx.lookup(systemLogger.getConfigurationParameters().getDataSource());
conn = wrapperDataSource.getConnection();
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver").newInstance();
conn = DriverManager.getConnection(url,login,password);
if (conn != null)
{
stmt = conn.createStatement();
res = stmt.executeQuery(query);
if (res != null)
{
while (res.next())
{
for (int i = 0; i < columnlength; i++)
{
String columnName = metadata.getColumnName(i+1);
if (metadata.getColumnName(i+1).equalsIgnoreCase(systemLogger.getColumnStatus()))
{
columnStatusType = metadata.getColumnType(i+1);
}
else if (metadata.getColumnName(i+1).equalsIgnoreCase(systemLogger.getColumnDocumentId()))
{
columnDocumentIdType = metadata.getColumnType(i+1);
}
else if (metadata.getColumnName(i+1).equalsIgnoreCase(systemLogger.getColumnTimer()))
{
columnTimerType = metadata.getColumnType(i+1);
}
}
}
}
else
{
__log.error("No results found for the query");
throw new PtmServiceException("No se encontraron resultados para el query");
}
}
else
{
__log.error("Could not create the connection");
throw new PtmServiceException("No se pudo crear la conexion");
}
}
catch(Exception e)
{
__log.error("Error in the execution of the query");
throw new PtmServiceException("Error ejecutando la busqueda");
}
finally
{
res.close();
stmt.close();
conn.close();
}
The variable columnlength seems to hold a value larger than the number of columns returned by the query. Try with a smaller columnlength.
finally, i see the problem, while i'm debugging the code with ecplise in the view of the expressions i added the follow expression res.next(), then each sentence that i pass for the step into bring the consequence that expression that evaluate if the resultset has more rows, be evaluated again. In some point the resultset has evaluated all the rows for each step into that i made in the process of debugging. The only thing that i have to do was eliminate the expression and works fine...
The problem might not be with the code but instead could be the database. Double check that the TABLE IS NOT EMPTY. You get this error if the table is empty. Keep in mind that databases like Oracle require a commit after all your insert, update, alter statements .Your changes might not be visible outside the database till you run a commit over the your db, I was having this problem for quite a long time. I kept on checking the table with select statement but the problem with my oracle db was that I had not issued a commit over my db.

Categories

Resources