1

I have LATEST_MODIFICATION_DATE field in my database table which is timestamp datatype. I am using plane jdbcTemplate for database execute queries.

Below is part of my code which is working fine. But I see an issue on the line

latestModDate = rowSet.getString("LATEST_MODIFICATION_DATE");

Because I am trying to treat LATEST_MODIFICATION_DATE timestamp datatype field as a string it might create problem in my code in future.

I tried to update the line below and then declare LATEST_MODIFICATION_DATE as timestamp datatype but getting error as oracle.sql.timestamp cannot be cast to java.util.date.

latestModDate = rowSet.getTimestamp("LATEST_MODIFICATION_DATE");

I really dont know how to treat LATEST_MODIFICATION_DATE as timestamp. I really dont want to make change in system property like below as i want to handle this issue in code:

java -Doracle.jdbc.J2EE13Compliant=true YourApplication
or
System.getProperties().setProperty("oracle.jdbc.J2EE13Compliant", "true")

Below is part of my code:

            String orderID = null, extOrdId = null, latestModDate = null;                

            while (rowSet.next()) {
                latestModDate = rowSet.getString("LATEST_MODIFICATION_DATE");
            }

            
Symonds
  • 184
  • 1
  • 2
  • 15

3 Answers3

1

You've defined latestModDate as a String but as you've said it's a timestamp in the database, if you change the type to something like java.util.Date and then use ResultSet.getDate() this should fix your problem:

Date latestModDate = rowSet.getDate("LATEST_MODIFICATION_DATE");
mohammedkhan
  • 953
  • 6
  • 14
  • i have changed the latestModDate type to java.util.Date latestModDate and then did the change you mentioned but still getting same error oracle.sql.TIMESTAMP cannot be cast to java.sql.Timestamp – Symonds Jun 28 '20 at 14:55
  • @Symonds this is a problem with the Oracle JDBC driver. Have a look at the discussion here: https://stackoverflow.com/questions/13269564/java-lang-classcastexception-oracle-sql-timestamp-cannot-be-cast-to-java-sql-ti – mohammedkhan Jun 28 '20 at 16:10
  • If i do like this then its working now: oracle.sql.TIMESTAMP latestModDate = null; latestModDate = (TIMESTAMP) rowSet.getObject("LATEST_MODIFICATION_DATE"); – Symonds Jun 28 '20 at 16:16
  • so declaration normally should not be java.util.Date but oracle.sql.TIMESTAMP – Symonds Jun 28 '20 at 16:17
  • 1
    @Symonds yes as per the discussion on that thread that is one solution. Adding a setting to the jvm means you could use my solution. (tbh I didn't realise this was a problem, I've always done it this way, someone must have added those settings to our project when it was first started 15 years ago). – mohammedkhan Jun 28 '20 at 16:23
1
  1. Declare latestModDate of type java.sql.Timestamp.

  2. Get java.time.Instant from latestModDate as follows:

    Instant instant = latestModDate.toInstant();
    

Once you have the object of Instant, you can convert it to any other modern date-time object as per your requirement e.g.

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;

public class Main {
    public static void main(String[] args) {
        Instant instant = Instant.now();
        ZonedDateTime zdt = instant.atZone(ZoneId.of("Europe/London"));
        OffsetDateTime odt = zdt.toOffsetDateTime();
        LocalDateTime ldt = zdt.toLocalDateTime();
        System.out.println(instant);
        System.out.println(zdt);
        System.out.println(odt);
        System.out.println(ldt);
    }
}

Output:

2020-06-27T08:55:12.317754Z
2020-06-27T09:55:12.317754+01:00[Europe/London]
2020-06-27T09:55:12.317754+01:00
2020-06-27T09:55:12.317754

Some additional notes:

  1. Do not use outdated and error-prone java.util date-time API. Use the modern date-time API.
  2. LocalDateTime drops off information like Zone Offset and Zone ID which may be required in your business logic. Therefore, choose the appropriate class as per the table shown below (Ref): enter image description here

[Update]

The changes that you need to make in your code:

java.sql.Timestamp latestModDate;

if (rowSet.next()) {
    latestModDate = ((oracle.sql.TIMESTAMP) rowSet.getObject("LATEST_MODIFICATION_DATE")).timestampValue();
}

// If the record exist, update accordingly, else insert a new one.
if (latestModDate != null) {
    String sqlUpdate = "update " + tableName + " set LATEST_MODIFICATION_DATE = sysdate, SOURCES = '" + fileName + "' where (ORDERID = '" + orderID + "' and EXTORDID = '" + extOrdId + "') or (ORDERID = '" + orderID + "' and EXTORDID is null)";
    jdbcTemplate.update(sqlUpdate);
    //...

Note: The function oracle.sql.TIMESTAMP#timestampValue returns a value in java.sql.Timestamp.

Arvind Kumar Avinash
  • 71,965
  • 6
  • 74
  • 110
  • sorry i am bit confused with the changes i have to do actually ...will be really helpful if you can please mentioned the changes i need to do thanks...specially this part i dont understand: Once you have the object of Instant, you can convert it to any other modern date-time object as per your requirement e.g. – Symonds Jun 28 '20 at 15:08
  • @Symonds - I've added an update in my answer. I hope, it helps. Feel free to comment in case of any doubt/issue. – Arvind Kumar Avinash Jun 28 '20 at 15:14
  • but are we still using rowSet.getString in your changes ? – Symonds Jun 28 '20 at 15:18
  • sorry still geting same error oracle.sql.timestamp cannot be cast to java.util.date – Symonds Jun 28 '20 at 15:23
  • @Symonds - Please post the error as a comment below this comment. – Arvind Kumar Avinash Jun 28 '20 at 15:25
  • its on line latestModDate = rowSet.getTimestamp("LATEST_MODIFICATION_DATE"); the error is : java.lang.ClassCastException: oracle.sql.TIMESTAMP cannot be cast to java.sql.Timestamp – Symonds Jun 28 '20 at 15:27
  • @Symonds - I've updated the code accordingly. Feel free to comment in case of any doubt/issue. – Arvind Kumar Avinash Jun 28 '20 at 15:38
  • its still throws same error but as per your given link i tries few changes and its working now but i have small isse in checking isEmpty()...please see last part of my edited question – Symonds Jun 28 '20 at 15:42
  • @Symonds - Remove `isEmpty()`. There is a function with this name in the class, `String` but not in `java.sql.Timestamp` class. I haven't used it in my code. – Arvind Kumar Avinash Jun 28 '20 at 15:44
  • sorry one question if i remove isEmpty() does it make really difference ? because i really want to check this condition otherwise empty rows will get inserted ? – Symonds Jun 28 '20 at 15:46
  • @Symonds - The check, `latestModDate != null` will do the work. – Arvind Kumar Avinash Jun 28 '20 at 15:47
0

Don't use java.sql.Date or java.util.Date. Use java.time.LocalDateTime. java.util.Date is a hack and java.sql.Date is a hack on top of a hack.

LocalDateTime latestModDate;

while (rowSet.next()) {
    latestModDate = rowSet.getObject("LATEST_MODIFICATION_DATE", LocalDateTime.class);
}
Douglas Surber
  • 622
  • 4
  • 9
  • i am using java 8 and i am getting the exception with the changes: org.springframework.jdbc.InvalidResultSetAccessException: Not supported yet.; nested exception is java.sql.SQLFeatureNotSupportedException: Not supported yet. – Symonds Jun 28 '20 at 15:05
  • As per @Symonds comment `ResultSet` doesn't support `java.time.*` classes. – mohammedkhan Jun 28 '20 at 16:07
  • If i do like this then its working now: oracle.sql.TIMESTAMP latestModDate = null; latestModDate = (TIMESTAMP) rowSet.getObject("LATEST_MODIFICATION_DATE"); – Symonds Jun 28 '20 at 16:16