Timestamp issue from ojdbc5 & ojdbc - java

JVM Timezone details : India Standard TimeAsia/Calcutta019800000
DB Timezone details : Central Standard TimeAmerica/Chicago3600000-21600000
Sample Code:
String sql = "select systimestamp as base from dual";
....
PreparedStatement stmt = con.prepareStatement(sql);
ResultSet rs = stmt.executeQuery();
while(rs.next()) {
System.out.println(rs.getTimestamp("base"));
System.out.println(rs.getString("base"));
}
Test-1:
I tested using ojdbc14.jar 10.1.0.3.0 with, it works as expected printing the db time
Output:
2013-12-05 01:23:57.141583
2013-12-5 1.23.57.141583000 -6:0
Test-2:
I tested using ojdbc5.jar & ojdbc6.jar 11.2.0.3.0 with, getTimestamp print local time where as getString prints db time.
Output:
2013-12-05 12:57:54.3508
2013-12-05 01:27:54.3508 -6:00
Please suggest what is wrong with Test-2 ojdbc driver version 11.2.0.3.0 where the getTimestamp() prints local time. My application expect the db time like Test-1 in the getTimestamp() where it matches with DB timestamp.

We had the same issue a few days ago at my company. The bottom line of this is you should never get a timestamp as a string (as it's database/driver specific) and always get the TimeStamp object and format it any way you want using a SimpleDateFormat.
And it's always worth mentioning that the Timestamp class is an abomination , from the javadocs
Due to the differences between the Timestamp class and the
java.util.Date class mentioned above, it is recommended that code not
view Timestamp values generically as an instance of java.util.Date.
The inheritance relationship between Timestamp and java.util.Date
really denotes implementation inheritance, and not type inheritance.

Related

Query using setDate does not find results - cannot see final-query with parameters

I have an SQL which looks into a dimension table (which stores every dates until year 2020) and then shall retrieve the todays row.
I watched into the table, todays date is in there.
The problem is, that SQL does not return any result.
I am thinking of a problem related to the use of java.sql.PreparedStatement.setDate method.
In past i think this was working fine, now I did some kine of regression test and it failed. The differences to the past are having Oracle 12 DB now instead of 11 in past and running it on CentOS 6.5 instead of AIX.
On search I found this topic here:
Using setDate in PreparedStatement
As far as I can see, I am doing as suggested.
Heres the java code and the query:
public static String SELECT_DATUM = "SELECT TIME_ID, DATE, DAY_NAME, WEEK_NAME, MONTH_NAME, YEAR_NAME, SORTING, RELATIONDATE, VALID_TO, VALID_FROM FROM DIM_TIME WHERE DATE = :date";
java.util.Calendar now = Calendar.getInstance();
now.clear(Calendar.HOUR);
now.clear(Calendar.MINUTE);
now.clear(Calendar.SECOND);
now.clear(Calendar.MILLISECOND);
Date tmpDate = now.getTime();
Date tmpDate2 = new Date(((java.util.Date)tmpDate ).getTime());
statement.setDate(1, tmpDate2 );
I notice that getTime() is called twice. But I dont think its that bad.
I also noticed some displaying formats:
in Database the date-colums shows me the date like this: '08.11.2015'
in java while debugging tmpDate2 shows me a date like this: '2015-11-08'
in java while debugging tmpDate shows me a date like this 'Sun Nov 08 12:00:00 CET 2015'
But again, these are just display formattings while it is a dateobject in background and a date-type in database. I would expect that je JDBC driver would map this itself without formattings, that why we are using setDate method and not setString.
What am I doing wrong? What could I do for further debugging to get it?
I would like see the resulting SQL query which is finally executed with the parameter.
I tried this sql on db isntance:
SELECT * FROM v$sql s WHERE s.sql_text LIKE '%select time%' ;
but only getting this then: "... where date = trunc(:1 )"
On this row at least I can see that it was using the right schema I expected it to use and where I checked whether todays date is available.
Edit:
something I found out:
I saw another code using the same function but giving an GregorianCalendar instead Calendar. When using
new GregorienCalandar();
instead of
Calendar.getInstance();
Theres no difference.
But when I assign a date and dont let the system take the current time, then it works:
Using
new GregorianCalendar(2015, Calendar.NOVEMBER, 8);
Would retrieve the row I want from SQL.
Zsigmond Lőrinczy posted this answer as comment:
Try this: SELECT TIME_ID, DATE, DAY_NAME, WEEK_NAME, MONTH_NAME,
YEAR_NAME, SORTING, RELATIONDATE, VALID_TO, VALID_FROM FROM DIM_TIME
WHERE DATE = TRUNC (:date) – 3 hours ago
This works for my problem.
I am writing this as reponse to check it later as answer on this question if hes not going to write his own response (to get the reputation-points).
But I am wondering how I could get the same by preparing on java.
The code uses the clear-methods, which where released into an own method named 'trunc'. I think the programmer intendet to do this instead of TRUNC in SQL. I am wondering if it werent possible to do so in java and if yes, how?
Edit:
And I am wondering why a TRUNC is needed at all. Because the column in Database is of type Date an not Timestampt. So wouldnt there be an automatically trunc? I would expect this. Why do I need a trunc on SQL?

Oracle JDBC - Date format difference

I have a Date type column in one of our tables and when I query the database I get the date from the resultset like:
final String createdDate = resultSet.getString("received_date");
If I run this on OC4J container on Java 5 I get
2014-12-26 05:57:31.0
while on Tomcat with Java 8 I get
2014-12-26 05:57:31
The JDBC driver are of different versions - do you think I should blame the driver for this? Is it a good direction regarding the investigation? Or is it more about Java version difference?
Thanks

Retrieving MySQL time in java

I am running the following query to get time difference of two times
resultSet = statement.executeQuery("SELECT TIMEDIFF('14:03:55.256', '14:02:51.780') AS td");
MySQL gives time difference in this format
00:01:03.476
But both
resultSet.getTime("td"); and resultSet.getObject("td");
returns 00:01:03
According to the documentation getTime(String string) retrieves the value of the designated column in the current row of this ResultSet object as a java.sql.Time object in the Java programming language.
java.sql.Time corresponds to SQL TIME and contains information about hour, minutes, seconds and milliseconds.Then why am I getting 00:01:03 instead of 00:01:03:476?
What I basically want is to store 00:01:03.476 into a String. Is there any workaround or I am doing it wrong?
If you are verifying the result by printing it out note that java.sql.Time.toString() only returns a string in the format hh:mm:ss
You should really use rs.getTimestamp which will return a java.sql.Timestamp
Try to do this:
String s = new SimpleDateFormat("HH.mm.ss.SSS").format(t.getTime());
where t is your variable of type java.sql.Time.
Hope this will solve you problem.

Calling Oracle stored procedure with DATE input doesn't set the HH:MM:SS

I'm trying to call an Oracle stored procedure in a Java EE web application (java) using Spring 'CallableStatementCreator'. One of the inputs for the stored procedure is a DATE.
My attributeValue is a java.util.date and it correctly holds both DD-MM-YYYY and HH:MM:SS.
When using the following code:
callableStmt.setTime(6, new java.sql.Time(attributeValue.getTime()));
The result is the column in the DB (the stored procedure ultimately writes in the DB) is set to 1970-01-01 and the correct HH:MM:SS I pass as input. This worked in a previous version of my application (where I used JDBC lib 10.x.x.x)
If I use
callableStmt.setDate(6, new java.sql.Date(attributeValue.getTime()));
The DD-MM-YYYY is set correctly but the hour is set to 00:00:00.
So, what's the correct way to call and pass the attribute to this stored procedure? Also, any debug tips?
Oracle Database 11g Enterprise Edition Release 11.2.0.2.0 - 64bit Production
Oracle JDBD lib: ojdbc6-11.2.0.3
Try using a Timestamp:
callableStmt.setTimestamp(6, new java.sql.Timestamp(attributeValue.getTime()));
Using
callableStmt.setTimestamp(6, new java.sql.Timestamp(attributeValue.getTime()));
Didn't work in my case where I have a stored procedure overloaded where the only difference between my 3 functions is this last parameter: VARCHAR2, DATE or NUMBER. When using this code, the execution of my stored procedure fails because Oracle can't find out which method to use. (probably because JDBC lib doesn't map the timestamp to DATE column, as explained here )
The only way it worked was with:
callableStmt.setObject(6, new java.sql.Timestamp(attributeValue.getTime()), OracleTypes.DATE);
which seems to force the mapping between my Timestamp to DATE column in Oracle stored procedure while keeping the DD-MM-YYYY and HH:MM:SS.

java.sql.SQLException: ORA-01843: not a valid month

I am getting the following error when inserting data into my oracle database.
java.sql.SQLException: ORA-01843: not a valid month
In database date is as: dd-MMM-yy (06-MAR-12)
I am converting 06-03-2012 to dd-MMM-yy by the following method:
String s="06-03-2012";
String finalexampledt = new SimpleDateFormat("dd-MMM-yy").format(new SimpleDateFormat("dd-MM-yyyy").parse(s));
So i got 06-Mar-12 which is same as the above database date format still i am getting the error. I am inserting as:
in index.jsp
String todaydate="";
Calendar calendar1 = Calendar.getInstance();
SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy");
todaydate = dateFormat.format(calendar1.getTime());
<input type="text" name="datename" value="<%=todaydate%>"/>
in servlet(doPost)
String s=request.getParameter("datename");
PreparedStatement ps=con.prepareStatement("insert into tablename(rest_dt, othercolname) values (to_date(?, 'dd-mm-yyyy'), ?)");
ps.setString(1, s);
ps.setString(2, otherstringdata);
int rs=ps.executeUpdate();
Any idea please
so make
("insert into mytablename (rest_dt) values to_date(?, 'DD-MM-YYYY')");
Try this
TO_DATE(?, 'DD-MM-YYYY','NLS_DATE_LANGUAGE = American')
// gets from Oracle docs
The datatype of your rest_dt columns is a DATE, so you need to supply one. You can use the TO_DATE function to convert a string to an Oracle DATE, so your insert statement
insert into tablename(rest_dt, othercolname) values (to_date(?, 'dd-mm-yyyy'), ?)
is fine.
Just make sure the string value you bind to your first ?-variable is in the format dd-mm-yyyy. And don't convert or format that value yourself: the TO_DATE function does that part.
There is no need to anything about session settings like nls_date_language here, since you have wisely chosen to use a language agnostic setting for the month with your MM mask (instead of MON).
Regards,
Rob.
Problem is that oracle uses NLS_DATE_LANGUAGE to get the current name of the month. So you should do
select * from nls_session_parameters
and check if you have the correct values. You can also check with the following select which name you get for the month
select TO_CHAR(TO_DATE('01-03-01', 'DD-MM-YY'), 'MON') from dual
I really don't understand why you insert the variable as a string value. Just use a date type (do the conversion on the client) in java and insert it without converting. If you really want to insert it as a string I would use a conversion to something like dd-MM-yyyy and insert it with TO_DATE(, 'DD-MM-YYYY').
Edit:
Do the conversion of the date on the client and use
ps.setDate(2, <yourDate>);
The same issue faced while running big query (multiple union) in Java and issue not with actual input since I have properly converted the with to_date('30-06-2021', 'dd-MM-yyyy') and found issue is with the date1 in query.
e.g.
select a,b,c from table1 where date1='31/12/2015'and date2=<actual input>
union
select a,b,c from table2 where date1='31/12/2015'and date2=<actual input>
union
select a,b,c from table3 where date1='31/12/2015'and date2=<actual input>
.
.
date1 also should be convert to to_date like below
e.g.
select a,b,c from table1 where date1=to_date('31/12/2015', 'dd-MM-yyyy') and date2=<actual input>
Hence issue resolved. My suggestions is, if you are getting such issues check the date part in the query and mention with to_date.
Java code:
#Autowired
private NamedParameterJdbcTemplate namedJdbcTemplate;
List<ResponseDTO> list = new ArrayList<>();
MapSqlParameterSource params = new MapSqlParameterSource();
params.addValue("value1", dto.getValue1());
params.addValue("value2", dto.getValue2());
list = namedJdbcTemplate.query(SQL_QUERY, params, new CustomValueMapper());
Its purely only my own experience. Click up vote if it helps.
java.time and JDBC 4.2
Don’t transfer a date as a string to or from your database. Transfer a proper date object. I am assuming that your JDBC driver is at least JDBC 4.2 compliant. About all drivers are these days. In this case LocalDate is the type to use for dates, both in your Java program and in the transfer to the database.
So what you basically need is this:
LocalDate date = LocalDate.of(2012, Month.MARCH, 6);
PreparedStatement ps = con.prepareStatement(
"insert into tablename(rest_dt, othercolname) values (?, ?)");
ps.setObject(1, date);
ps.setString(2, otherstringdata);
int rs = ps.executeUpdate();
If you are receiving your date as string input from JSP, immediately parse it into a LocalDate object. There’s no need to wait until you need to put it into your database.
String inputString = "06-03-2012"; // Meaning 6 March 2012
LocalDate date = LocalDate.parse(inputString, DATE_PARSER);
I have been using this formatter:
private static final DateTimeFormatter DATE_PARSER
= DateTimeFormatter.ofPattern("dd-MM-uuuu", Locale.ROOT);
Links
Oracle tutorial: Date Time explaining how to use java.time.
Related question: Insert & fetch java.time.LocalDate objects to/from an SQL database such as H2

Categories