Strange problem with JDBC, select returns null - java

I am trying to use JDBC and my query is working in some cases but not working in others.
I would really appreciate any help.
Some of my code:
public Result getSpecificTopic()
{
String query = "Select msg_body, msg_author from lawers_topic_msg";// where msg_id=2 order by msg_id desc";
try
{
con = mysql.getConnection();
//Statement stmt = con.createStatement();
PreparedStatement stmt = con.prepareStatement(query);
//stmt.setInt(1, topicId);
ResultSet rs = stmt.executeQuery(query);
int rowCount = rs.getRow();
specificTopic = ResultSupport.toResult(rs);
con.close();
stmt.close();
}
catch(Exception e)
{
}
return this.specificTopic;
}
public void setTopicId(String num)
{
this.topicId = Integer.parseInt(num);
}
public int getTopicId()
{
return this.topicId;
}
However if i change
String query = "Select msg_body, msg_author from lawers_topic_msg";
to the
String query = "Select msg_body, msg_author from lawers_topic_msg where msg_id = " + topicId;
Then the resultset retunrs nothing....
I am breaking my head here and still cannot figure out what is the problem

You still aren't closing your resources properly. That should be done in a finally block:
http://www.java-blog.com/correct-closing-jdbc-resources

As a first step, it'd be worth making sure an exception's not being thrown - at the very least log something in your catch() block.
Also be worth logging the SQL generated, and making sure that actually returns what you expect from the database when running it directly.
If you have multiple databases, it'd be worth confirming you're running against the one you think you are - I'm embarrassed to admit I've been caught out that way before.

several issues with your code, i'll keep it short:
don't encapuslate with try / catch at this layer, aspecially not since you're doing no error management. this.specificTopic looks global, so if your query fails it will return whatever was stored in this.specificTopic.
also try what BobbyShaftoe said. print in console or use your debugger. This should give you a good indication on what is wrong.

my first guess would be Integer.parseInt(num) could throw an exception. if so, the sql statement will be broken.
secondly, as Makach pointed out, there are several issues. first the catch-all
you should not use string concatenation, like
....where msg_id = " + topicId;
but rather
....where msg_id = ?"
stmt.set Int(1,topicId)
edit: it seems thats what you were trying anyways, SO sucks in some characters.

Related

MySql Connector SQL Statement does not return any values under java

I am using mySQL Connector in java and I need to write this long query where I join tables and return stocks of particular user. User_ID would be supplied by the java program hence i got ? and passed into the database. However I assume due to syntax error in java it does not return any values to program and simply fails. Query works perfectly in database.
String a = jTextField_User_Name.getText();
PreparedStatement ps = null;
String queryretrive = "SELECT DISTINCT Stock_Name FROM stockname,users,stock,userstock WHERE 'users.ID' = ? AND users.ID = userstock.User_ID AND userstock.Stock_ID = stock.Stock_ID AND stock.Stock_ID = stockname.Stock_ID";
ResultSet rs;
try {
ps = MyConnector.getConnection().prepareStatement(queryretrive);
ps.setString(1,a);
rs = ps.executeQuery();
if(rs.next())
{
System.out.println(rs.getString("Stock_Name"));
}else{
JOptionPane.showMessageDialog(null, "Error");
}
} catch (SQLException ex) {
Logger.getLogger(LoginForm.class.getName()).log(Level.SEVERE, null, ex);
}
Thanks.
WHERE 'users.ID' = ? AND users.ID =
Obviously, the second reference to users.ID doesn't need to be quoted, so why did you attempt to quote the first one?
Anyway, in MySQL " and ' are used to quote string literals and ` (backtick) is used to quote identifiers. If ANSI_QUOTES SQL mode is enabled, then " is used to quote identifiers, like other DBMS dialects do.
If you do need to quote, you need to quote each part separately, so the correct quoting would be `users`.`ID` or "users"."ID".
The fact that ' sometimes work for quoting identifiers is just weird lenient behavior and shouldn't be used, since it easily confused with string literals. Don't even know how MySQL decides whether it's a string literal or an identifier, so it's best to never do it.
this query is not long but this is hard to understand without your data model and code example.
if this is working in MySQLWorkBench should works from java. If this is not working from java you have poor error handling, or you haven't set properly parameter.
'users.ID' may be just users.ID
remove try/catch for testing purpose or handle this catch.
BTW.
With java/mysql ALWAYS handle finally to free connection, something like :
finally
{
try {if (rs != null) rs.close();} catch(Exception e) {}
try {if (statement != null) statement.close();} catch(Exception e) {}
}

results.next() == false and there's no printing of data

results.next() is false, !results.next() in the while loop prints ResultSet closed
I've tried EVERYTHING. from doing Class.forName() to connection.setAutoCommit(false) nothing's working :/
public static void main(String[] args) throws Exception {
String query = "SELECT * FROM StudentInfo";
String url;
try {
Class.forName("org.sqlite.JDBC");
connection = DriverManager.getConnection(url);
ps = connection.prepareStatement(query);
results = ps.executeQuery();
while (results.next()) {
print(results.getString("nameID"));
}
} catch (SQLException e) {
print(e.getMessage());
}
}
just prints out BUILD SUCCESSFUL without printing any of my data
The first thing to consider is to make sure that the table isn't empty.
Class.forName isn't even assigned to anything.
connection.setAutoCommit(false) is irrelevant here as that's more of a transaction detail. You don't need to worry about that for a query this simple.
I'd try running a query that you know works first. Maybe your connection isn't even correct or possibly null, thus never really executing the query. That's probably why your resultset is closed.
I also hope print() is from System.out or something that will actually print.

What is wrong with my query?? It has no error at all

I have a problem with my sql query in Java. As you can see below, the query is supposed to return rph_id but it returns only 0, so it only proceeds to the else method.
At first, I did not use prepareStatement but many suggest that I use prepareStatement. But it still won't work. After checking both suggestions, I think my problem is on the query but I don't know what.
public class RphDAO{
static int rph_id;
public static RPHS getRph(RPHS rph) {
try {
currentCon = ConnectionManager.getConnection();
ps=currentCon.prepareStatement("select * from rphs where rph_id=?");
ps.setInt(1, rph_id);
ResultSet rs = ps.executeQuery();
if (rs.next()) {
rs.getInt("rph_id");
rph.setRph_id(rph_id);
rph.setValid(true);
} else {
rph.setValid(false);
}
}
...
return rph;
}
}
It should return an existing id, not 0.
Here:
if (rs.next()) {
rs.getInt("rph_id");
rph.setRph_id(rph_id);
rph.setValid(true);
You get a value from the ResultSet rs ... to then throw that result away.
Probably you meant something like:
rph_id = rs.getInt("rph_id");
On the other hand, your request those entries that have rph_id==1, so I don't see what other value than 1 you expect to find here. Most likely, you want to look into other parts of that result set, and somehow pull those into variables/fields of some object.
It seems as if the OP is simply not familiar with using ResultSet, thus I think the real answer is: go and read a good tutorial on this subject. You can't learn how to use a new API by trial and error. Read its documentation, or a good tutorial that shows you how to use it properly!
I think you should use COUNT instead in your sql since it is no point in setting the id if it is already correct and also use the id from the object given as parameter to the method for consistency.
public static RPHS getRph(RPHS rph) {
try {
currentCon = ConnectionManager.getConnection();
ps=currentCon.prepareStatement("select COUNT(*) from rphs where rph_id=?");
ps.setInt(1, rph.getRph_id);
ResultSet rs = ps.executeQuery();
int count = 0;
if (rs.next()) {
count = rs.getInt(1);
}
rph.setValid(count == 1);
}

JDBC exception handling: warning suppression

I am currently learning some basic java SQL coding, making a basic terminal UI for my SQL project. I have been using PostgreSQL
I am using PreparedStatement to ensure myself from SQL injections, better be safe than sorry. PreparedStatement seems to always fire warnings for some reason, which I figured is a subclass to exceptions (and should get caught in the exceptions).
In my SQL triggers and functions I have created and tested the cases where I should fire exceptions, and they are all getting and working properly catch block.
I guess using #Supresswarnings to let the compiler know I want to do suppress my warnings, but I might want to catch some warnings in the catch block, so I might be looking for a different solution.
The problem / question is:
I would like to have my prints in the try block, that is no exceptions were fired.
What could be done to have my prints after the execution of preparedStmt.executeQuery in the try block?
Is using #SuppressWarnings usually considered good coding practice when dealing with exception handling like this?
If I am incorrect about preparedStatement.executeQuery() always fires warnings, what is considered warnings in SQL language?
My code:
void registerStudent(Connection conn, String toBeInserted, String insertedTo)
throws SQLException{
ResultSet res;
String query = "INSERT INTO Registrations VALUES (?, ?)";
PreparedStatement ps = conn.prepareStatement(query);
ps.setString(1, toBeInserted);
ps.setString(2, insertedTo);
try {
ps.executeQuery();
}catch (SQLException e) {
SQLWarning warning = ps.getWarnings();
if (warning != null){
System.out.println("Yay, insert succeeded!
values: "+ toBeInserted +" were inserted into
"+insertedTo);
}else {
System.out.println("Nothing inserted, here goes the big exception SQL fired for ya'll: "
+ e.getMessage());
}
}
}
There are still some flaws. I added also the case of an AUTOINCREMENT primary key - which you can retrieve after inserting.
Flaws:
List which fields you insert, such that a later addition of a column in the database does not cause problems, and the order of columns is clear in the code.
Use try-with-resources to close statement, result set and such, even when one returns inside, or an exception is thrown.
Use executeUpdate for INSERT (and similar modifying operations) returning an update count.
You catched the SQLException, which then should be rethrown, to let the caller determine what to do on gross failure.
SQLWarnings (as does the actual SQL and the SQLException) might be interesting,
though I not often see SQLWarnings being treated. Maybe forget it for such simple case, and instead try new SQL statements first in a separate SQL tool.
So:
/**
* #return the generated primary key, the Student ID.
*/
int registerStudent(Connection conn, String toBeInserted, String insertedTo)
throws SQLException {
String query = "INSERT INTO Registrations(ToBeInserted, InsertedInto) VALUES(?, ?)";
try (PreparedStatement ps = conn.prepareStatement(query),
Statement.RETURN_GENERATED_KEYS) {
ps.setString(1, toBeInserted);
ps.setString(2, insertedTo);
int updateCount = ps.executeUpdate();
if (updateCount == 1) {
try (ResultSet rs = ps.getGeneratedKeys()) {
if (rs.next()) {
int id = rs.getInt(1);
return id;
}
}
throw new SQLException("No primary key generated");
} else {
SQLWarning warning = ps.getWarnings();
Logger.getLogger(Xyz.class.getName()).info("Not added, values: "
+ toBeInserted + " were not inserted into "+ insertedTo + ": " + warning);
throw new SQLException("Not added");
}
}
}
Thank you very much I know I really shouldn't respond to your post but it helped be a lot. I think I got confused about ps.executeQuery() and ps.executeUpdate() methods.
executeQuery() generated a warning because there was nothing being returned, although it did work to execute the update to the database with that method.
The other tips and tricks is something I will bear with me as well.

Resultset not open

I get following error on Result set
java.sql.SQLException: ResultSet not open. Verify that autocommit is OFF.
at org.apache.derby.client.am.SQLExceptionFactory40.getSQLException(Unknown Source)
at org.apache.derby.client.am.SqlException.getSQLException(Unknown Source)
at org.apache.derby.client.am.ResultSet.next(Unknown Source)
public ResultSet insertDb(int Id,String firstName,String lastName,String title) throws SQLException{
try {
try {
Class.forName(driver);
con = DriverManager.getConnection(connectionURL);
} catch (SQLException ex) {
Logger.getLogger(Connect.class.getName()).log(Level.SEVERE, null, ex);
} catch (ClassNotFoundException ex) {
Logger.getLogger(Connect.class.getName()).log(Level.SEVERE, null, ex);
}
System.out.println(con.getAutoCommit());
statement = con.createStatement() ;
res = statement.executeQuery("SELECT * FROM CUSTOMER") ;
con.setAutoCommit(false);
System.out.println(con.getAutoCommit());
while(res.next()){
if(res.getString("ID").equalsIgnoreCase(Integer.toString(Id))){
UNIQUE = false;
error= "Duplicate Entry Found Please Enter New Data";
throw new SQLException("Duplicate info<br>ID " + Id );
}
}
// IF value to be added IS UNIQUE
if(UNIQUE){
String qry1= "insert into CUSTOMER(ID, FIRSTNAME,LASTNAME,TITLE) values(?,?,?,?)";
stm = con.prepareStatement(qry1);
String ID=Integer.toString(Id);
stm.setString(1, ID);
stm.setString(2, firstName);
stm.setString(3, lastName);
stm.setString(4, title);
stm.executeUpdate();
}
}
catch(Exception e){
String errorMessage = "Exception caught : ";
System.out.println(errorMessage + e.toString());
}finally{
if (con != null){
con.close();
}
}
return res;
}
Try moving the setAutoCommit() and getAutoCommit() to before you create and execute the statement. Changing it after you execute the statement may be invalidating the query.
The problem is that you have closed your query before reading your resultset. Closing the query, closes the resultset, hence why you get the "ResultSet not open" error. You should close the query right at the end, in a finally block:
i.e. con.setAutoCommit(false);
will close the query and along iwth it it closes the resultset also.
Not strictly related, but your code probably doesn't do what you expect. This kind of read-modify-write code doesn't work well when there are multiple concurrent invocations.
If you imagine two invocations running though the code, it becomes clear that sometimes, depending on the execution order, BOTH invocations could reach the insert statement.
In addition, selecting from a table without using a WHERE clause is not generally useful. In this case you select '*', then iterate over all the results to see if "ID" == Id. The database is much much better at that than java is. You should add a where clause. (Note that this still won't solve the above problem)
Its also generally a bad idea to 'select *' from any table. Just pick the columns that you need. This will 'fail fast' if the schema changes and the columns that you need are no longer available, and will allow the database optimiser to do the 'right thing' about its disk accesses.
Finally, if its just a numeric ID that you are looking to assign, its normal practice to use 'autonumber' for these, rather than get the program to pick them. Different databases call them different things, so you might also know them as IDENTITY, or have to use a sequence.
In case it helps anyone down the line, I had the same error with Derby 10.5.1.1 that turned out to be a bug in the driver itself that would appear some times and not others depending on the underlying data. Upgrading the driver to a newer version (10.8.2.2) resolved the problem.

Categories

Resources