Inserting NULL for NUMBER column - java

I am trying to insert NULL value for my NUMBER column in H2 database.
In my Java model the corresponding value is Long (not primitive). Now, I am aware how JDBC driver inserts 0 for nulls if not specified, but I do exactly that.
My DAO layer is in Spring, and for this exact column I am mapping its value in this manner.
if(user.getDefaultNumber() == null){
map.addValue("defaultNumber", user.getDefaultNumber(), Types.NULL);
}else{
map.addValue("defaultNumber", user.getDefaultNumber());
}
However, this does not seem to be working. I have tracked it deep into Spring Core classes, and null value for my object is there, but somewhere it still gets turned to 0.
Can someone please help me, this is bugging me for days.

Please try PreparedStatement to save null value in integer column
pst.setNull(4, java.sql.Types.INTEGER);
enter link description here

The solution to the problem was adding Types.Integer. I am still not sure why it did not work with Types.NULL but I will investigate. For now this is the solution
if(user.getDefaultNumber() == null){
map.addValue("defaultNumber", user.getDefaultNumber(), Types.INTEGER);
}else{
map.addValue("defaultNumber", user.getDefaultNumber());
}
Also, it is very important to map it properly when reading from DB. JDBC will read NULLs from database, but it will still insert 0 in Java's attribute. So, if reading is not handled properly as well, it might leave an impression that the problem persists even though the writing part is actually OK.

Related

What is causing Java program to treat the two ResultSet.getString() methods differently?

If "FirstName" and index 1 refer to the same column in a query, and rs is a ResultSet, why would
if(rs.getString("FirstName")!=null) fullName = rs.getString("FirstName");
and
if(rs.getString(1)!=null) fullName = rs.getString(1);
behave differently?
According to the Java docs, using either the columnIndex or the columnLabel
both return the value of the designated column.
I'm running into a weird problem when I use the columnIndex instead of the columnLabel, for some reason, after the jsp has been running for a few hours/days then if(rs.getString(1)!=null) evaluates to true even when the String is null. When I use the columnLabel instead, the problem doesn't happen. Can anyone tell me why this might be happening?
Extra background info
The program runs in Tomcat. We updated Tomcat, the JVM, and our database driver on the same day, and this started happening. If we reload the app in Tomcat, it starts working correctly, at least for a few hours. We switched back to the old database driver and the problem continues, so we have ruled out the database driver.
rs.getString(1) returns the data for the first column in your SQL query executed (by the preparedStatement), it need NOT be the FirstName, you need to cross check that your SQL query in preparedStatement is as follows:
SELECT FirstName from X;//you might add where conditions
From your comment:
it just starts returning the String "null" instead of the actual null value. So the fullName becomes the String "null".
In other words the problem is different from what is stated in your question. null and "null" aren't the same thing, so there is no reason for rs.getString(1) == null to return true if the actual value is "null".
I would say you probably have "null" in your database somewhere. Check. Or else you are using String.valueOf(null) somewhere in your code, possibly indirectly, e.g. via println(null), which calls it, so the output is "null".
We have solved it. We decided to try a different SQL driver (we were using a Microsoft driver before, we switched to JTDS) and all problems have gone away.
So I'm guessing the Microsoft driver was returning the string "null" when it should have been returning null.
So to answer the question, the ResultSet.getString() method was probably behaving correctly all along, but the SQL driver was returning bad data.

SQL JAVA EE WHERE statement isn't taken into account

I connect to a database with something like 50 tables, referenced in a table inside the database. The problem I'm having, is for one of these table, the WHERE statement in the SQL query is simply not taken into account by the query, like it was inexistent. I tried a lot of thing, like using row index instead of row name to reference it in the query. I searched for a while but nobody seems to have had the same problem.
It's strange because it happens in only one query, all the other work just fine, on the same type of data, same WHERE. So the solution is probably dumb, but at this point I need another point of view.
The second query below works just fine, but it's just as if the WHERE statement wasn't there... But the first one achieve is goal as intended.
resultCompare = compareStat.executeQuery("SELECT Nb_doc_Notes, Nb_doc_SQL FROM Comparaison_Replique_Resultats WHERE Table_SQL_associee = '"+tableName+"' ORDER BY ID_Comparatif DESC;");
resultCompare.next();
int numberLines = resultCompare.getInt("Nb_doc_Notes");
numberEntries = resultCompare.getInt("Nb_doc_SQL");
resultCompare.close();
resultCompare = compareStat.executeQuery("SELECT ID_Comparatif FROM Comparaison_Replique_Resultats WHERE Difference = "+REQUIRED_DIFFERENCE+" ORDER BY ID_Comparatif DESC;");
resultCompare.next();
int ID = resultCompare.getInt("ID_Comparatif");
resultCompare.close();
So when I check the "ID_Comparatif", it just get the last one in the table, ignoring the fact that Difference is almost everytime different from REQUIRED_DIFFERENCE (equals to 0 BTW, it's just that during my preliminary testing I tried putting the value in a variable and then concatenating it, just like in others query I have in the program.
Thanks !

Weird Behavior of ResultSet

hello mates hope you having a nice day, i have a really weird problem with getting data from Mysql database in Java , in the method here :
ResultSet tableExistence;
.
.
.
while (tableExistence.next()) {
System.out.println("before : "+tableExistence.getInt(MyHttpServer.COL_ID));
if(tableExistence.getString(MyHttpServer.COL_STATUS).equals(MyHttpServer.STATUS_AVAILABLE)){
System.out.println("after : "+tableExistence.getInt(MyHttpServer.COL_ID));
...
}
weirdly the value of the "before" is for the right value of the id , but after the if method, the value of "after" returns some thing like 1234125151231 , any idea why is this problem ?!!!!
The ResultSet documentation states:
The docs do say "For maximum portability, result set columns within each row should be read in left-to-right order, and each column should be read only once."
So technically, it's somewhat reasonable. However:
I would actually expect that any modern, well-supported database would allow you to access the columns in an arbitrary order, multiple times
Just returning an incorrect value rather than throwing an exception to indicate the problem is pretty nasty
One explanation could be if you're fetching a clob or blob - the driver may decide in that case that "left to right only" is more reasonable, to avoid having to keep too much data in memory. It's still not great that it just returns corrupted data though.
So while this is a possible answer, I would also:
Check that neither the connection nor the ResultSet is being used from multiple threads concurrently
Check that you're using a recent version of the MySQL driver

Form duplication of field, before MySQL posting of data

I have almost managed to fix a long standing problem I've been having with duplicate fields in my website, today I got a very quick solution to make the column data unique. An easy fix that had escaped me.
However this leaves an auto increment entry to the database, with null values except for ID (primary column). You can see the effect this has in the website, LostDots.com
I have tried all the INSERT IGNORE options, and this didn't fix it either.
So I was thinking if it might be possible to use the validate form coding to eliminate entires before it gets sent to MySQL. i.e.
if (theForm.Editbox2.value == "")
{
alert("at least put a X");
theForm.Editbox2.focus();
return false;
}
if (theForm.Editbox2.value.length < 1)
{
alert("at least put a X");
theForm.Editbox2.focus();
return false;
}
As an example of what I was thinking, maybe if I pulled up the variable for the Editbox2 value, and got it to compare?
if (theForm.Editbox2.value = $namevariable)
{
alert("That domain name has already been advertised !!");
theForm.Editbox2.focus();
return false;
}
Having previously queried the present table data
(SELECT EDITBOX2 FROM TABLE1 WHERE NOT EXISTS $namevariable);
I am only wondering if this could be possible, I think getting the variable into Java is the problem? Maybe I haven't slept enough and speaking jibberish.
Let me know if it might be possible. Thanks, Alastair.

How to retrieve previously auto-generated PK ID value using JDBC and HSQLDB

I'm working with JDBC and HSQLDB 2.2.9. What's the most efficient and accurate way to insert a new row into a DB and, subsequently, retain its id (PK set to autoincrement) value? The reason I need to do this is probably pretty obvious, but I'll illustrate with an example for discussion:
Say there's a Customer table that has a PersonId field with a FK constraint referring to a row from a Person table. I want to create a new Customer, but to do this I need to first create a new Person and use the new Person.id value to set Customer.PersonId.
I've seen four ways to approach this:
Insert the Person row setting the id field to null. HSQLDB generates the next id value automatically. Then perform a query on the Person table to get the id value just created and use it to create the new Customer row.
This seems expensive just to retrieve a single integer value.
Get the next id value in the Person table and use it in the INSERT statement to set the Person.id value manually. Use the same id value to set Customer.PersonId. No subsequent read from the DB is needed.
Inconsistencies may arise if an id value is obtained, but another connection performs an INSERT in the table before my INSERT INTO Person... statement is executed.
Execute the INSERT statement, as in option 1 above, setting id=null to allow auto-generation. Then use the getGeneratedKeys method to retrieve keys generated in last statement.
I thought this sounded like a good option, but I couldn't get it to work. Here's a snippet of my code:
// PreparedStatement prepared previously...
preparedStatement.executeUpdate();
ResultSet genKeys = preparedStatement.getGeneratedKeys();
int id;
if (genKeys.next()) {
id = genKeys.getInt(1);
}
// Finish up method...
This code was returning an empty ResultSet for genKeys. Am I using the getGeneratedKeys method incorrectly? If I could get this to work, this might be the way to go.
Again, execute the INSERT statement allowing for auto-generated id. Then immediately execute CALL IDENTITY() to retrieve the last id value generated by the connection (as explained here and mentioned in this SO question).
This also seems like a reasonable option, even though I must perform an additional executeQuery. On the positive side, I was actually able to get it to work with the following code:
// INSERT statement executed here...
statement = connection.createStatement();
ResultSet rs = statement.executeQuery("CALL IDENTITY();");
int id;
if (rs.next()) id = rs.getInt(1);
// Finish up method...
So, in summary, the first two options I'm not crazy about. The second two seem ok, but I could only get option 4 to work. Which option is preferred and why? If option 3 is the best, what am I doing wrong? Also, is there a better way that I haven't mentioned? I know words like 'better' can be subjective, but I'm working with a simple DB and want the most direct solution that doesn't open up the DB to possible inconsistencies and doesn't increase the transaction failure rate (due to trying to create a record with an id that already exists).
This seems like a basic question (and essential), but I couldn't find much guidance on the best way to do it. Thanks.
EDIT:
I just found this question that discusses my option 3. According to the accepted answer, it appears I was leaving out the Statement.RETURN_GENERATED_KEYS parameter needed to enable that functionality. I didn't show the prepareStatement method in my code snippet, but I was using the single parameter version. I need to retry using the overloaded, two-parameter version.
There are also a few other SO questions which show up with that question that are closly related to my question. So, I guess mine could be considered a duplicate (not sure how I missed those other questions before). But I'd still like any guidance on whether one solution is considered better than the others. For now, if I get option 3 to work, I'll probably go with that.
I don't have enough reputation to comment on neizan's answer, but here's how I solved the same problem:
The column looked like an ID column, but it wasn't defined as IDENTITY;
As said above, you need to specify RETURN_GENERATED_KEYS.
It looks like if you execute 2 INSERT in sequence, the second one won't return the generated keys. Use "CALL IDENTITY()" instead.
Example using HSQLDB 2.2.9:
CREATE TABLE MY_TABLE (
ID INTEGER IDENTITY,
NAME VARCHAR(30)
)
Then in Java:
PreparedStatement result = cnx.prepareStatement(
"INSERT INTO MY_TABLE(ID, NAME) VALUES(NULL, 'TOM');",
RETURN_GENERATED_KEYS);
int updated = result.executeUpdate();
if (updated == 1) {
ResultSet generatedKeys = result.getGeneratedKeys();
if (generatedKeys.next()) {
int key = generatedKeys.getInt(1);
}
}
Not much action here, so I'll go ahead and answer to bring closure to this question. After playing around with the different options, and after see this question, I was able to get my option 3 to work. Like I mentioned in the edit to my question, I'm going to use option 3. Option 4 also worked fine, but since the accepted answer to the linked question is given by a reputable source, I am sticking with that. I wish I'd have seen that question/answer before starting this one, I'd have saved some time!

Categories