db-ojb-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Martin Kalén <martin.ka...@curalia.se>
Subject Nanosecond precision makes optimistic locking unusable with Oracle
Date Mon, 21 Jun 2004 18:50:51 GMT

While working through the test case failures with db-ojb HEAD and Oracle9i,
I came across OptimistictLockingTest.testTimestampLock() that constantly
threw a mysterious OptimisticLockingException after trying to delete the
inserted row (after an expected failed concurrent update).

Failing statements (line 155 in CVS HEAD):
   if(!broker.isInTransaction()) broker.beginTransaction();

Call-stack top without org.apache.ojb.broker package prefix:
org.apache.ojb.broker.OptimisticLockException: Object has been modified or deleted by 
someone else
	at accesslayer.JdbcAccessImpl.executeDelete(JdbcAccessImpl.java:102)
	at core.PersistenceBrokerImpl.doDelete(PersistenceBrokerImpl.java:495)
	at core.PersistenceBrokerImpl.delete(PersistenceBrokerImpl.java:445)
	at core.DelegatingPersistenceBroker.delete(DelegatingPersistenceBroker.java:169)
	at core.DelegatingPersistenceBroker.delete(DelegatingPersistenceBroker.java:169)
	at OptimisticLockingTest.testTimestampLock(OptimisticLockingTest.java:156)

Looking at ClassDescriptor.java, lines 949 and 950 in method updateLockingValues,
one sees that the locking timestamp is created using "new java.sql.Timestamp(long)".

If doing this is seems that at least for Oracle JDBC thin driver, the naonsecond
part of the Timestamp can be initialized to values != 0.

Since Oracle TIMESTAMP does not have nanosecond precision, the value for comparision
when reading back from the DB will _always_ have Timestamp.getNanos() == 0.

Hence; the timestamp in memory and the comparision value read from the db will differ
and OptimisticLockingException thrown were it should not.

The solouting for Oracle9i is to clear the nanosecond part of the Timestamp when
creating new locking values, e.g. inserting "ts.setNanos(0)" in
ClassDescriptor.updateLockingValues. Like this:
Index: src/java/org/apache/ojb/broker/metadata/ClassDescriptor.java
RCS file: 
retrieving revision 1.87
diff -r1.87 ClassDescriptor.java
<                     f.set(obj, new Timestamp(newCv));
 >                     Timestamp ts = new Timestamp(newCv);
 >                     ts.setNanos(0);
 >                     f.set(obj, ts);

It would be really good if people could try this out on other platforms and if
the maintainers of the locking code could think through if this would imply
negative consequences elsewhere.

If it's OK and the diff above is applied before 1.0 final it will mean a major
  improvement for using OJB with Oracle.


Martin Kalén
Curalia AB              Web:  http://www.curalia.se
Orrspelsvägen 2B        Mail: info@curalia.se
SE-182 79  Stocksund    Tel:  +46-8-410 064 40

To unsubscribe, e-mail: ojb-dev-unsubscribe@db.apache.org
For additional commands, e-mail: ojb-dev-help@db.apache.org

View raw message