How to check for null when using getDouble("columnName")? - java

I need to retrieve a double value from a database, which could potentially be stored as null, so I need to detect whether or not it is null before or after retrieving it. However, the method getDouble("columnName") actually returns 0 if the value in the database is null.
I have tried the solutions provided here to no avail (Android Studio says it's unable to resolve wasNull() and getObject():
How do I in JDBC read a possibly null double value from resultSet?
Here is what I've tried so far:
beer.setRating(beerObj.getDouble("myRating"));
if(beerObj.wasNull()){ //'Cannot resolve method wasNull'
}
And this:
Double doubleVal = (Double)beerObj.getObject("myRating"); //'Cannot resolve method getObject()'
I have other properties that I am retrieving using getString("otherColumnName") and that is retrieved properly so I assumed that the beerObj was retrieved properly as well.
Is there another way to check if the double value is null in the database before retrieving it?

Yes put it in your where clause: "WHERE columnname is not null". If there is a record returned then it isn't null if there isn't a record returned then it is null.

Try if (resultset.getObject("columnName") == null). It's hard to tell from your original post if you were trying to use getObject() without passing in a value.

Related

Getting Unknown object type when trying to set null using TYPES.NULL

I am trying to execute a update statement using JDBC and I am trying to set null values like below.
updateStmt.setNull(j + 1, Types.NULL);
But when ever this statement gets executed I get the below error.
java.sql.SQLException: Unknown object type
at com.informix.util.IfxErrMsg.getSQLException(IfxErrMsg.java:355)
at com.informix.jdbc.IfxValue.createInstanceFromClassName(IfxValue.java:403)
at com.informix.jdbc.IfxValue.makeInstanceFromIfxType(IfxValue.java:635)
at com.informix.jdbc.IfxValue.makeInstanceFromIfxType(IfxValue.java:610)
at com.informix.jdbc.IfxValue.makeInstance(IfxValue.java:390)
at com.informix.jdbc.IfxPreparedStatement.setNull(IfxPreparedStatement.java:396)
What am I doing wrong ? Please help
Not all databases have a dedicated NULL data type, and it seems Informix is one of them.
For best portability use the actual type of the column with a null value.
For example (assuming the column type is VARCHAR, adjust as needed):
updateStmt.setString(j + 1, null);
Or:
updateStmt.setNull(j + 1, Types.VARCHAR);
Don't put Types.NULL. Instead use the Type of the column you want to insert the null into.

How to make a method calling an SQL query that returns a blank string instead of NULL when the query result is empty?

I have a method which runs a JDBC call into a database to gather expected results which I then assert against with results gathered from UI using another method using Selenium.
The problem I'm facing here is that it's possible for the query to not get any results so when I call the method which would send back a string, it actually sends back NULL when the query result is empty.
This causes problems when I try to assert against the UI values. Selenium will return an empty string for the value in question while the db returns NULL.
So to get my assertEquals to match I ideally want the db method to return "" instead of NULL.
I've tried a .replace and an IF statement but it always returns NULL.
The code from my JDBC method looks like this in case this helps:
String strMedicare = rs.getString("_Provider_Number");
return strMedicare;
One way to handle this on the SQL side would be to modify your query to the following:
SELECT COALESCE(_Provider_Number, '') AS _Provider_Number
FROM yourTable
...
Then, your database would automatically return empty string in case the provider number should be null.

How to pass blank value to date or time data type field while calling api

Currently I am working on the project where I want to pass the blank value to date data type field in api and in return want blank or null value to that field.
For ex.
xyz.org/v1/serviceUpdate?RecordID=103&Name=Aazad+Hind1&Age=75&DOB=****&token=retretretrt222343
What should I pass in **** place so that empty value get passed to DOB field.
I try with NULL value but it gave me the following error
SQLSTATE[22007]: [Microsoft][ODBC Driver 11 for SQL Server][SQL Server]Conversion failed when converting date and/or time from character string.
while hitting the below url
xyz.org/v1/serviceUpdate?RecordID=103&Name=Aazad+Hind1&Age=75&DOB=&token=retretretrt222343
It is storing 01/01/1900 default value.I want blank or null value instead of default value in response.
Anyone know about how to achieved this without doing any changes in third party api let me know
This is possible when your DOB field in the database is defined as DEFAULT NULL as shown below.
DOB date DEFAULT NULL
Source : https://stackoverflow.com/a/13934665/5644934

Hibernate expected NUMBER got BINARY on null field

I can't understand why Hibernate is trying to set this field as a VARBINARY when it is null.
The Java data type is BigDecimal
The Oracle data type is Float
It is being set like this:
entityManager.createNamedQuery("blah").setParameter("target_field", object.sourceValue)
again - sourceValue is a BigDecimal, and when i debug it the value is null.
when it tries to execute this update, I get oracle error:
ORA-00932: inconsistent datatypes: expected NUMBER got BINARY
this is what shows up for this property in the console log:
o.h.type.descriptor.sql.BasicBinder : binding parameter [8] as [VARBINARY] - [null]
IF I do this silly hack in Java before I execute the update:
if (object.sourceValue == null) object.sourceValue = new java.math.BigDecimal(0);
Then it runs fine. So the cause of this error is definitely not anything else than hibernate doing something wrong when the field is null.
How do I fix this so I can set the field to null without hibernate mishandling it?
In the DB, the field is nullable.
It looks the issue has not been resolved yet even with newer version of hibernate 5.2.17.Final with JPA.
The null parameter is being sent as VARBINARY which causes the error
ERROR [org.hibernate.engine.jdbc.spi.SqlExceptionHelper] - ERROR: cannot cast type bytea to bigint
One workaround to this is to use the org.hibernate.Query that is wrapped into the org.hibernate.ejb.QueryImpl this way:
QueryImpl q = (QueryImpl) this.entityManager.createNamedQuery("myNamed.query");
q.getHibernateQuery().setParameter("name", value, org.hibernate.Hibernate.BIG_DECIMAL);
q.getResultList();
When value is null, hibernate still can know which type the parameter must be, so it doesn't translate the null to a binary value.
I have solved this problem by adding 2 annotations
#DynamicUpdate(value=true)
#DynamicInsert(value=true)
Also and most important, check mapping on your entity class for getters like (onetomany, manytoone).
All the best.

What is the correct usage of zxjdbc to call stored procedures?

I am attempting to use zxJDBC to connect to a database running on SQL Server 2008 R2 (Express) and call a stored procedure, passing it a single parameter. I am using jython-standalone 2.5.3 and ideally do not want to have to install additional modules.
My test code is shown below.
The database name is CSM
Stored Procedure:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author: <Author,,Name>
-- Create date: <Create Date,,>
-- Description: <Description,,>
-- =============================================
CREATE PROCEDURE dbo.DUMMY
-- Add the parameters for the stored procedure here
#carrierId VARCHAR(50)
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for procedure here
INSERT INTO dbo.carrier (carrierId, test)
VALUES (#carrierId, 'Success')
END
GO
Jython Script:
from com.ziclix.python.sql import zxJDBC
conn = None
try :
conn = zxJDBC.connect('jdbc:sqlserver://localhost\SQLEXPRESS', 'sa', 'password', 'com.microsoft.sqlserver.jdbc.SQLServerDriver')
cur = conn.cursor()
cur.callproc(('CSM','dbo','DUMMY'), ['carrier1'])
conn.commit()
except Exception, err :
print err
if conn:
conn.rollback()
finally :
if conn :
conn.close()
By using cur.execute() I have been able to verify that the above is successfully connecting to the database, and that I can query against it. However, I have thus far been unable to successfully call a stored procedure with parameters.
The documentation here(possibly out of date?) indicates that callproc() can be called with either a string or a tuple to identify the procedure. The example given -
c.callproc(("northwind", "dbo", "SalesByCategory"), ["Seafood", "1998"], maxrows=2)
When I attempt to use this method, I receive the following error
Error("Could not find stored procedure 'CSM.DUMMY'. [SQLCode: 2812], [SQLState: S00062]",)
It would appear that zxJDBC is neglecting to include the dbo part of the procedure identifier.
If I instead call callproc with "CSM.dbo.DUMMY" as the first argument then I receive this error
Error('An object or column name is missing or empty. For SELECT INTO statements, verify each column has a name. For other statements, look for empty alias names. Aliases defined as "" or [] are not allowed. Change the alias to a valid name. [SQLCode: 1038], [SQLState: S0004]',)
Using a profiler on the database whilst running my script shows that in the second case the following SQL is executed:
use []
go
So it would seem that when using a single string to identify the procedure, the database name is not correctly parsed out.
One of my trial and error attempts to fix this was to call callproc as follows:
cur.callproc(('CSM', '', 'dbo.DUMMY'), ['carrier1'])
This got me only as far as
Error("Procedure or function 'DUMMY' expects parameter '#carrierId', which was not supplied. [SQLCode: 201], [SQLState: S0004]",)
In this case what I think is happening is that zxJDBC attempts to call a system stored procedure (sp_proc_columns) to determine the required parameters for the stored procedure I want to call. My guess is that with the procedure identifier in the incorrect format above, zxJDBC does not get a valid/correct return and assumes no parameters are required.
So basically I am not a bit stuck for ideas as to how to get it to
Use the correct database name
Correctly determine the required parameters using sp_proc_columns
Call my stored procedure with the correct name
all at the same time.
I do have a workaround, which is to use something like
cur.execute('EXEC CSM.dbo.DUMMY ?', ['carrier1'])
However I feel like callproc() is the correct solution, and would likely produce cleaner code when I come to call stored procedures with large numbers of parameters.
If anyone can spot the mistake(s) that I am making, or knows that this is not ever going to work as I think then any input would be much appreciated.
Thanks
Edit
As suggested by i-one, I tried adding cur.execute('USE CSM') before calling my stored procedure (also removing the database name from the procedure call). This unfortunately produces the same Object or Column missing error as above. The profiler shows USE CSM being executed, followed by USE [] so it seems that callproc() always fires a USE statement before the procedure itself.
I have also experimented with turning on/off autocommit, to no avail.
Edit 2
Further information following comments/suggested solutions:
"SQLEXPRESS" in my connection string is the database instance name.
Using double quotes instead of single has no effect.
Including the database name in the connection string (via ;databaseName=CSM; as specified here) and omitting it from the callproc() call leads to the original error with a USE [] statement being fired.
Using callproc(('CSM', 'dbo', 'dbo.DUMMY'), ['carrier1']) gives me some progress but results in the error
Error("Procedure or function 'DUMMY' expects parameter '#carrierId', which was not supplied. [SQLCode: 201], [SQLState: S0004]",)
I'll attempt to investigate this further
Edit 3
Based on the queries I could see zxJDBC firing, I manually executed the following against my database:
use CSM
go
exec sp_sproc_columns_100 N'dbo.DUMMY',N'dbo',N'CSM',NULL,N'3'
go
This gave me an empty results set, which would seem to explain why zxJDBC isn't passing any parameters to the stored procedure - it doesn't think it needs to. I have yet to figure out why this is happening though.
Edit 4
To update the above, the empty result set is because the call should be
exec sp_sproc_columns_100 N'DUMMY',N'dbo',N'CSM',NULL,N'3'
This unfortunately brings me full circle as I can't remove the dbo owner from the stored procedure name in my callproc() call or the procedure won't be found at all.
Edit 5
Table definition as requested
CREATE TABLE [dbo].[carrier](
[carrierId] [varchar](50) NOT NULL,
[test] [varchar](50) NULL
) ON [PRIMARY]
Though completely unaware of the technologies used here (unless some minor knowledge of SQL Server), I will attempt an answer (please forgive me if my jython syntax is not correct. I am trying to outline possibilities here not exact code)
My first approach (found at this post) would be to try:
cur.execute("use CSM")
cur.callproc(("CSM","dbo","dbo.DUMMY"), ["carrier1"])
This must have to do with the fact that sa users always have the dbo as a default schema (described at this SO post)
If the above does not work I would also try to use the CSM database name in the JDBC url (this is very common when using JDBC for other databases) and then simply call one of the two below.
cur.callproc("DUMMY", ["carrier1"])
cur.callproc("dbo.DUMMY", ["carrier1"])
I hope this helps
Update: I quote the relevant part of the link that you can't view
>> Program calls a Stored Procedure - master.dbo.xp_fixeddrives on MS SQL Server
from com.ziclix.python.sql import zxJDBC
def getConnection():
url = "${DBServer.Url}"
user= "${DBServer.User}"
password = "${DBServer.Password}"
driver = "${DBServer.Driver}"
con = zxJDBC.connect(url, user, password, driver)
return con
try:
conn = getConnection()
print 'Connection successful'
cur = conn.cursor()
cur.execute("use master")
cur.callproc(("master", "dbo", "dbo.xp_fixeddrives"))
print cur.description
for a in cur.fetchall():
print a
finally:
cur.close()
conn.close()
print 'Connection closed'
The error you get when you specified the call function like above suggests that the parameter is not passed correctly. So please modify your stored procedure to take a default value and try to call with passing params = [None]. If you see that the call succeeds we must have done something right as far as specifying the database is concerned.
Btw: the most recent documentation suggests that you should be able to access it with your syntax.
As outlined in comments callproc will work only with SELECT. Try this approach instead:
cur.execute("exec CSM.dbo.DUMMY #Param1='" + str(Param1) + "', #carrierId=" + str(carrierID))
Please see this link for more detail.

Categories