How to tell if timestamp from Postgres in Java is null - java

The code below is a snippet from a back-end REST service I have touched on. I'm wondering how to tell if a timestamp I'm getting is null. I've learned through trial and error that if the timestamp is null in the Postgres database that when I bring it into Java that if its null it will get instantiated as a new DateTime at the current time of operation. What can I do to check get and set nulls dynamically according to model data?
public List<SubscriptionEntityModel> getAllSubscriptions(PagingInfoDomainModel paging) throws Exception {
Database db = new Database();
String stmt = "{call sp_subscriptions_get_all(?, ?)}";
if(AppConfig.data.isDebug) {
logger.debug("Running database operation.. " + stmt);
}
CallableStatement sproc = db.dbEndpoint.prepareCall(stmt);
sproc.setInt(1, paging.pageCurrent);
sproc.setInt(2, paging.pageItemCount);
ResultSet rs = sproc.executeQuery();
List<SubscriptionEntityModel> subscriptions = new ArrayList<SubscriptionEntityModel>();
while(rs.next()) {
SubscriptionEntityModel subscription = new SubscriptionEntityModel();
subscription.subscriptionId = rs.getInt("subscription_id");
subscription.name = rs.getString("name");
subscription.emailAddress = rs.getString("email_address");
subscription.phoneNumber = rs.getString("phone_number");
subscription.organizationId = rs.getInt("organization_id");
subscription.createdAt = new DateTime(rs.getTimestamp("created_at"));
subscription.expiredAt = new DateTime(rs.getTimestamp("expired_at"));
subscriptions.add(subscription);
}
sproc.close();
db.destroy();
return subscriptions;
}

Check out ResultSet#wasNull
https://docs.oracle.com/javase/7/docs/api/java/sql/ResultSet.html#wasNull()
Reports whether the last column read had a value of SQL NULL.
Hence you can use it after rs.getTimestamp() to check if the value read was SQL NULL, but note that ResultSet#getTimestamp already returns a null reference if that was the case.
https://docs.oracle.com/javase/7/docs/api/java/sql/ResultSet.html#getTimestamp(int)
the column value; if the value is SQL NULL, the value returned is null
The problem you're facing is that when you pass a null reference to the constructor of DateTime, it will be interpreted as now.

java.sql.Timestamp getTimestamp(String columnLabel) throws SQLException;
will return null if the SQL field is NULL.
The problem is the way you instantiate your DateTime object.
With JodaTime (I give this example as you don't specify the used library), executing the following code creates indeed a DateTime instance with the actual date time :
java.sql.Timestamp timestamp = null;
DateTime dateTime = new DateTime(timestamp);
So to solve your problem, what you could do is checking the returned value by the resultset.
If it is not null, use it to create the DateTime object.
Otherwise don't use it and leave to nullthe DateTime field of the SubscriptionEntityModel you are setting properties.
So instead of doing :
subscription.createdAt = new DateTime(rs.getTimestamp("created_at"));
You should do :
java.sql.Timestamp createdAt = rs.getTimestamp("created_at");
if (createdAt != null){
subscription.expiredAt = new DateTime(createdAt);
}

Related

What Date types are timezone specific?

I have a calendar object with timezone specific. I want to update my sql server table using this object. However, it throws an error if I use calendar object in my unit test. I use hsqldb to test it with datetime as column type.
Therefore, I need to use different type for time. I tried using Timestamp object, it works, but it is not timezone specific. Here is my code:
private SqlParameterSource getParameters(StudyEvent studyEvent) {
MapSqlParameterSource parameters = new MapSqlParameterSource();
parameters.addValue(STUDY_ID, studyEvent.getStudy().getId());
parameters.addValue(STUDY_DATE, new Timestamp(getDate(studyEvent.getStudy().getStudyDate()).getTimeInMillis()));
//studyEvent.getStudy().getStudyDate() returns long value of time (epoch time)
}
private Calendar getDate(long time) {
Calendar calendar = new GregorianCalendar(TimeZone.getTimeZone("America/New_York"));
calendar.setTimeInMillis(time);
return calendar;
}
In new Timestamp(.....) code, it won't be timezone specific which I need. What are other Date type object I can use so it is converted from Calendar and add it to sql server with timezone specific?
Edit:
I have a piece of code using prepared statement that allows me to use timestamp and timezone like this:
private long insertStudy(StudyEvent event) {
KeyHolder keyHolder = new GeneratedKeyHolder();
int records = jdbcTemplate.getJdbcTemplate().update(connection -> {
PreparedStatement statement = connection.prepareStatement(insertStudy, new String[] { STUDY_ID });
int index = 1;
statement.setTimestamp(index, new java.sql.Timestamp(Instant.now().toEpochMilli()), CALENDAR);
return statement;
}, keyHolder);
return keyHolder.getKey().longValue();
}
PreparedStatement.setTimestamp() looks like a possible solution, but I am not sure how to use PreparedStatement to SqlParameterSource..

Insert jspinner time value to database

I have two jspinners. the one contains an HH:mm format and the other one is a simple number(int) spinner.
when SAVE button clicked I want to update a database table that contains the timeLimit (type time) and attempts (type int) columns. But I dont know how to save a jspinner value to a time type in my database.
String update = "Update qbank SET timeLimit = ? and attempts = ? where qbankID = ?";
preparedStatement = connection.prepareStatement(update);
preparedStatement.setTime(1, spinnerTime.getValue());
i tried the code above but the last part has an error saying spinnerTime.getValue is an object and setTime() requires a Time. How can I convert and object to time? or is there other way to insert a jspinner with time value to my database? any help would be appreciated!
It was just a simple overlooked problem. I just did this code.
Time time; int attempt;
time = (Time) spinnerTime.getValue();
attempt = Integer.parseInt(spinnerAttempt.getValue().toString());
String update = "Update qbank SET timeLimit = ? and attempts = ? where qbankID = ?";
preparedStatement = connection.prepareStatement(update);
preparedStatement.setTime(1, time);
preparedStatement.setInt(2, attempt);
preparedStatement.setInt(3, qbankID);
preparedStatement.executeUpdate();

Date format in an Oracle stored procedure called from Java

I am trying to use an Oracle stored procedure to update a database table. I am calling the procedure from a Java program. I want my procedure to accept dates in the format '01-01-2015' but for some reason my procedure will only accept a date if it is formatted as '01-JAN-2015'.
My stored procedure:
DELIMITER //
CREATE OR REPLACE PROCEDURE updateAward
(
p_award_id IN awards.award_id%TYPE,
p_award_date IN awards.award_date%TYPE,
p_total_amount IN awards.total_amount%TYPE,
p_number_sales IN awards.number_sales%TYPE,
p_emp_id IN awards.emp_id%TYPE
)
AS
BEGIN
UPDATE awards
SET award_date = to_date(p_award_date, 'DD-MM-YYYY'),
total_amount = p_total_amount,
number_sales = p_number_sales,
emp_id = p_emp_id
WHERE award_id = p_award_id;
COMMIT;
END;
/
The java code that calls it:
public boolean updateByID(Connection conn, String strVar, int[] intVar, double doubleVar)
{
System.out.println(strVar);
System.out.println(doubleVar);
System.out.println(intVar[0]);
System.out.println(intVar[1]);
System.out.println(intVar[2]);
try
{
String query = "{call updateAward(?,?,?,?,?)}";
CallableStatement stmt = conn.prepareCall(query);
stmt.setInt(1,intVar[0]);
stmt.setString(2, strVar);
stmt.setDouble(3, doubleVar);
stmt.setInt(4, intVar[1]);
stmt.setInt(5, intVar[2]);
stmt.executeUpdate();
return true;
}
catch(SQLException e)
{
System.out.println(e.getMessage());
}
return false;
}
The console print out of the variables being passed:
12-12-2012
65165.2
21
22
3
The error itself:
KORA-01843: not a valid month
ORA-06512: at line 1
Every solution that I have found has been to put the date format in the procedure. I believe I have done it with
award_date = to_date(p_award_date, 'DD-MM-YYYY'),
Have I written it incorrectly? Can someone please help?
Currently you are passing a String:
stmt.setString(2, strVar);
And you are parsing a String:
award_date = to_date(p_award_date, 'DD-MM-YYYY')
But you are expecting a Date in your custom type, and that is where the conversion fails. Change that to VARCHAR (or VARCHAR2) and it will work.
You're passing a string to a procedure that's expecting an Oracle date argument, via setString(). That means Oracle has to do an implicit conversion of the string to a date as part of the call, using the session/locale NLS_DATE_FORMAT, before you reach your to_date() call.
You could change your procedure argument type from awards.award_date%TYPE to varchar2, and still do the explicit conversion inside the procedure. Or you can leave the procedure signature as it is and pass the correct data type by converting it on the Java side, e.g.:
SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy");
cStmt.setDate(2, new java.sql.Date(sdf.parse(strVar).getTime()));
And as p_date is already a date, you should not call to_date() on that, as it will do an implicit conversion back to a string (using NLS_DATE_FORMAT again) and then try to explicitly convert that back to a date using the format model you supplied, which is also likely to give a similar error. Simplify that to just:
SET award_date = p_award_date,

Cant insert an empty date value into mysql

String datum = datumInvoer.getText();
**String bdate = bdatumInvoer.getText();**
String[] speler = spelers.getSelectedItem().toString().split(" ");
String[] toernooi = toernooien.getSelectedItem().toString().split(" ");
try {
PreparedStatement query = con.prepareStatement("INSERT INTO `fullhouse`.`inschrijving_toernooi` ( `IT_datum`, `IT_betaaldatum`, `speler`, `toernooi`) VALUES (?, ?, ? ,?)");
query.setString(1, datum);
query.setString(2, bdatum);
query.setString(3, speler[0]);
query.setString(4, toernooi[0]);
query.execute();
i have set the default to NULL , but it still wont insert it i am close to changing the datatype to varchar.
ERROR: incorrect date value
delimiter $$
CREATE TABLE `inschrijving_toernooi` (
`IT_code` int(11) NOT NULL AUTO_INCREMENT,
`IT_datum` date DEFAULT NULL,
`IT_betaaldatum` date DEFAULT NULL,
`speler` int(11) NOT NULL,
`toernooi` int(11) NOT NULL,
PRIMARY KEY (`IT_code`),
UNIQUE KEY `aaa` (`speler`,`toernooi`),
KEY `FS_code_idx` (`speler`),
KEY `FT_code_idx` (`toernooi`),
First Convert your date parameter from string to date. For that follow code below.
String bdate = bdatumInvoer.getText();
// get the correct date Format
// follow the link to get correct date format
// throws ParseException
Date date = new SimpleDateFormat("dd-MM-yyyy").parse(bdate);
Class SimpleDateFormat API
Now in prepared statement set them as date like shown below. As your table structure allows date in table.
query.setDate(2, date);
Now you still want to set null to that column then you can use and tell your query to set null by using following format in prepared statement.
query.setNull(2, java.sql.Types.DATE);
OR
query.setDate(2, null);
setNull API
Mapping of java.sql.Types to SQL types
I think this will solve your issue.
You need to change how you are passing parameters to you prepared statement
It should be something like below. And datum and bdatum should be of type Date. If you do not use what types are defined in your db you could put pass invalid data to your sql which would cause exceptions.
query.setDate(1, datum);
query.setDate(2, bdatum);
query.setInt(3, speler[0]);
query.setInt(4, toernooi[0]);
I suspect your bdatum variable contains an empty string. If you want to insert a SQL null, you need to pass in null, not empty string. (When I tried this on my machine with a similar insert, I got an "Incorrect date value" when trying to insert an empty string, but not with a null.)
if ("".equals(bdatum))
bdatum = null;
ps.setString(2, bdatum);
When you pass in a string in JDBC for a date value, MySQL will try to parse it, but empty string ("") is not a valid value. This works similarly to if you tried to do an insert with a date literal:
INSERT INTO `some_table` (`some_nullable_date_column`) VALUES ('2000-01-01') -- this works
INSERT INTO `some_table` (`some_nullable_date_column`) VALUES (NULL) -- this works
INSERT INTO `some_table` (`some_nullable_date_column`) VALUES ('') -- this fails
As an aside, passing in a string for a date value is semantically wrong and possibly less robust than parsing the string to a Date object before passing it to the PreparedStatement.

fetch records based on today's date

I wish to generate reports for my application, one such report requires to display list of orders given today. For that I have the following method in my ejb which returns nothing (debugged and found so):
public Collection<OrderStock> getOrderReport(String userName) {
String strQuery = null;
strQuery = "Select o from OrderStock o where o.userName.userName = :userName and o.orderDateTime = :orderDateTime";
Collection<OrderStock> c = em.createQuery(strQuery).setParameter("userName",userName).setParameter("orderDateTime", new Date(),TemporalType.DATE).getResultList();
return c;
}
How do i solve it? Why does it return nothing?
edited:
I am using mysql as backend
datatype of orderDateTime is DateTime
eg os data in orderDateTime : 2012-06-05 00:12:32
2012-06-05 11:34:42
2012-04-05 12:32:45
You have a DateTime column, and are looking for posts on a single date. I suspect this datetime column contains seconds or miliseconds since the Epoch. You can't compare times to dates, so you will have to convert the day to a time. Actually two times that describe the day.
SELECT o
FROM OrderStock o
WHERE
o.userName.userName = :userName
AND (
o.orderDateTime >= FirstSecondOfTheDay
OR o.orderDateTime <= LastSecondOfTheDay
)
Depending on your database system you can calculate these seconds (or milliseconds, i don't know your table) using the database or rather do it in java
You can not use Date() as simple as that. The date persisted in the DB will definitely have different format. So the best thing to do is to look into the method used to persist the data in the first place and use the same method to fetch back the data.
The method might by Oracle function, java method. You need to investigate further into this.
Try this for MySQL:
strQuery = "Select o from OrderStock o where o.user.userName = :userName and date(o.orderDateTime) = :orderDateTime";
Date today = DateUtils.truncate(new Date(), Calendar.DATE);
Collection<OrderStock> c = em.createQuery(strQuery).setParameter("userName",userName).setParameter("orderDateTime", today ,TemporalType.DATE).getResultList();

Categories