views:

57

answers:

1

Hi everyone,

This seems like such a bonehead question, but I've been chasing my tail around a tree all day. I have a Struts 2 + Spring3/JPA/Hibernate application that inserts a large set into the DB. In the set is a Java util date. I've checked the date just before the Dao inserts the rows and all the dates have the correct times. After insert, all the rows in the Oracle DB have no time, just the date. It's as if the time is truncated, but no errors appear in the transaction.

I thought before I posted any code, I would ask the question to see if someone could suggest something I may have been overlooking? The DB is Oracle 10g. JPA 2.0. The Column has the annotation on it:

@Column(name = "READING_DATE")
@Temporal(TemporalType.DATE)
private Date readingDate;

Setting the Column type to TemporalType.TIMESTAMP results in a Hibernate exception

column READING_DATE. Found: date, expected: timestamp

Any/all replies are appreciated.

+2  A: 

For this kind of problems, it usually helps to provide the version of the JDBC driver and the dialect you're using.

Anyway, my understanding is that you actually want the following mapping (for DATE and TIME):

@Column(name = "READING_DATE")
@Temporal(TemporalType.TIMESTAMP)
private Date readingDate;

And the problem you're facing is somehow related to the madness introduced by Oracle with version 9.2, see What is going on with DATE and TIMESTAMP? (in short, they introduced a TIMESTAMP column and changed the mapping of the DATE SQL type, read the FAQ). There are several options to solve it (I am of course assuming you are using a TemporalType.TIMESTAMP mapping):

Either use a TIMESTAMP column type (I don't mean TemporalType.TIMESTAMP here, I really mean the column type on the DB side). But if you don't need nanosecond precision, this is not the best choice.

Or set the oracle.jdbc.V8Compatible=true compatibility mode, either as system property or as a connection property:

<property name="hibernate.connection.oracle.jdbc.V8Compatible">true</property>

Yes, you can set arbitrary connection properties like this. From the Hibernate documentation:

3.3. JDBC connections

...

Arbitrary connection properties can be given by prepending "hibernate.connection" to the connection property name. For example, you can specify a charSet connection property using hibernate.connection.charSet.

Or use Oracle JDBC 11.1 driver (they "fixed" the problem by reverting the change). This is IMO the ideal solution (the V8Compatible stuff is deprecated).

Related issue

Pascal Thivent
That's in one word, Madness!
BalusC
@BalusC: Can't agree more.
Pascal Thivent
Wow, very well thought out reply. Thanks! I tried adding the v8Compatible parameter to my persistence.xml file, with the same result. I am using the JDBC driver that ships with the 10g download package and have the dialect set to Oracle10gDialect. On a side note, If I create a NativeQuery using the EM and loop through the result set doing an insert into the table the date/time makes it to the DB as expected. Given that, do you think the problem is still related to the JDBC driver? Should I still download the Ora 11 JDBC driver and use that instead?
Griff
I upgraded my JDBC Driver to 11... From my log file:INFO: RDBMS: Oracle, version: Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - ProductionINFO: JDBC driver: Oracle JDBC driver, version: 11.1.0.7.0-ProductionThe problem still persists. ;-(
Griff
@Griff: Hmm... I was pretty confident to be honest. But I'm confused now. Just to be sure, when do you get the problem: when inserting through JPA/Hibernate? When reading? or both? What mapping did you use during the test (TemporalType.TIMESTAMP or TemporalType.DATE)?
Pascal Thivent
@Pascal, the problem occurs when I am inserting the set (which is a set of objects that include a date column.) It's a master/detail type of scenario. The detail objects are the one with the date column. The column is annotated with TemporalType.DATE. The problem exists when I set the child <Set> on the parent object and allow the ORM to insert the child rows. Using a different approach, I wrote a Dao mehtod that loops through the child objects and inserts them using a NativeQuery. The result is that the date/time is inserted correctly, but the insert method is about 50% slower.
Griff
@Griff My suggestion was to use `TemporalType.TIMESTAMP` if you want the time part too.
Pascal Thivent
@Pascal, I missed that. I only want the time in seconds. Not Nanoseconds.... I'll give that a try.
Griff
Changing the TemporalType to TIMESTAMP and upgrading to Oracle 11 JDBC driver does the trick. Thanks for all the help! Incredible demonstration of skill and knowledge on your part. Cheers~
Griff
@Griff I clarified my answer. There was a possible confusion between the `TIMESTAMP` **column type** and `TemporalType.TIMESTAMP` (that nanosecond thing applies to the column type). Anyway, glad it's solved.
Pascal Thivent