You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openjpa.apache.org by ht...@apache.org on 2014/05/01 05:10:57 UTC

svn commit: r1591540 - in /openjpa/branches/2.3.x: ./ openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/ openjpa-kernel/src/main/java/org/apache/openjpa/kernel/ openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/optlockex/ openj...

Author: hthomann
Date: Thu May  1 03:10:56 2014
New Revision: 1591540

URL: http://svn.apache.org/r1591540
Log:
OPENJPA-2476: Fixed OptimisticLockEx due to rounding of a Timestamp

Added:
    openjpa/branches/2.3.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/optlockex/
      - copied from r1591536, openjpa/branches/2.1.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/optlockex/
    openjpa/branches/2.3.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/optlockex/timestamp/
      - copied from r1591536, openjpa/branches/2.1.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/optlockex/timestamp/
    openjpa/branches/2.3.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/optlockex/timestamp/TestTimestampOptLockEx.java
      - copied unchanged from r1591536, openjpa/branches/2.1.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/optlockex/timestamp/TestTimestampOptLockEx.java
    openjpa/branches/2.3.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/optlockex/timestamp/VersionTSEntity.java
      - copied unchanged from r1591536, openjpa/branches/2.1.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/optlockex/timestamp/VersionTSEntity.java
Modified:
    openjpa/branches/2.3.x/   (props changed)
    openjpa/branches/2.3.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionary.java
    openjpa/branches/2.3.x/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/StateManagerImpl.java
    openjpa/branches/2.3.x/openjpa-project/src/doc/manual/ref_guide_dbsetup.xml

Propchange: openjpa/branches/2.3.x/
------------------------------------------------------------------------------
  Merged /openjpa/branches/2.1.x:r1591536

Modified: openjpa/branches/2.3.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionary.java
URL: http://svn.apache.org/viewvc/openjpa/branches/2.3.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionary.java?rev=1591540&r1=1591539&r2=1591540&view=diff
==============================================================================
--- openjpa/branches/2.3.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionary.java (original)
+++ openjpa/branches/2.3.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionary.java Thu May  1 03:10:56 2014
@@ -96,6 +96,7 @@ import org.apache.openjpa.jdbc.schema.Fo
 import org.apache.openjpa.kernel.Filters;
 import org.apache.openjpa.kernel.OpenJPAStateManager;
 import org.apache.openjpa.kernel.Seq;
+import org.apache.openjpa.kernel.StateManagerImpl;
 import org.apache.openjpa.kernel.exps.Path;
 import org.apache.openjpa.lib.conf.Configurable;
 import org.apache.openjpa.lib.conf.Configuration;
@@ -1287,24 +1288,13 @@ public class DBDictionary
     public void setTimestamp(PreparedStatement stmnt, int idx,
         Timestamp val, Calendar cal, Column col)
         throws SQLException {
-        // ensure that we do not insert dates at a greater precision than
-        // that at which they will be returned by a SELECT
-        int rounded = (int) Math.round(val.getNanos() /
-            (double) datePrecision);
-        int nanos = rounded * datePrecision;
-        if (nanos > 999999999) {
-            // rollover to next second
-            val.setTime(val.getTime() + 1000);
-            nanos = 0;
-        }
         
-        Timestamp valForStmnt = new Timestamp(val.getTime());
-        valForStmnt.setNanos(nanos);
-
+        val = StateManagerImpl.roundTimestamp(val, datePrecision);
+        
         if (cal == null)
-            stmnt.setTimestamp(idx, valForStmnt);
+            stmnt.setTimestamp(idx, val);
         else
-            stmnt.setTimestamp(idx, valForStmnt, cal);
+            stmnt.setTimestamp(idx, val, cal);
     }
 
     /**

Modified: openjpa/branches/2.3.x/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/StateManagerImpl.java
URL: http://svn.apache.org/viewvc/openjpa/branches/2.3.x/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/StateManagerImpl.java?rev=1591540&r1=1591539&r2=1591540&view=diff
==============================================================================
--- openjpa/branches/2.3.x/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/StateManagerImpl.java (original)
+++ openjpa/branches/2.3.x/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/StateManagerImpl.java Thu May  1 03:10:56 2014
@@ -25,6 +25,7 @@ import java.io.ObjectOutput;
 import java.io.ObjectOutputStream;
 import java.io.Serializable;
 import java.lang.reflect.Modifier;
+import java.sql.Timestamp;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.BitSet;
@@ -159,6 +160,8 @@ public class StateManagerImpl implements
     
     private transient ReentrantLock _instanceLock = null;
 
+    private int _datePrecision = -1;
+        
     /**
      * <p>set to <code>false</code> to prevent the postLoad method from
      * sending lifecycle callback events.</p>
@@ -716,13 +719,48 @@ public class StateManagerImpl implements
     public void setNextVersion(Object version) {
         assignVersionField(version);
     }
+    
+    public static Timestamp roundTimestamp(Timestamp val, int datePrecision) {
+        // ensure that we do not insert dates at a greater precision than
+        // that at which they will be returned by a SELECT
+        int rounded = (int) Math.round(val.getNanos() / (double) datePrecision);
+        long time = val.getTime();
+        int nanos = rounded * datePrecision;
+        if (nanos > 999999999) {
+            // rollover to next second
+            time = time + 1000;
+            nanos = 0;
+        }
 
+        val = new Timestamp(time);
+        val.setNanos(nanos);
+        return val;
+    }
+    
     private void assignVersionField(Object version) {
+
+        if (version instanceof Timestamp) {
+            if (_datePrecision == -1) {
+                try {
+                    OpenJPAConfiguration conf = _broker.getConfiguration();
+                    Class confCls = Class.forName("org.apache.openjpa.jdbc.conf.JDBCConfigurationImpl");
+                    if (confCls.isAssignableFrom(conf.getClass())) {
+                        Object o = conf.getClass().getMethod("getDBDictionaryInstance").invoke(conf, (Object[]) null);
+                        _datePrecision = o.getClass().getField("datePrecision").getInt(o);
+                    } else {
+                        _datePrecision = 1000;
+                    }
+                } catch (Throwable e) {
+                    _datePrecision = 1000;
+                }
+            }
+
+            version = roundTimestamp((Timestamp) version, _datePrecision);
+        }
         _version = version;
         FieldMetaData vfield = _meta.getVersionField();
         if (vfield != null)
-            store(vfield.getIndex(), JavaTypes.convert(version,
-                vfield.getTypeCode()));
+            store(vfield.getIndex(), JavaTypes.convert(version, vfield.getTypeCode()));
     }
 
     public PCState getPCState() {

Modified: openjpa/branches/2.3.x/openjpa-project/src/doc/manual/ref_guide_dbsetup.xml
URL: http://svn.apache.org/viewvc/openjpa/branches/2.3.x/openjpa-project/src/doc/manual/ref_guide_dbsetup.xml?rev=1591540&r1=1591539&r2=1591540&view=diff
==============================================================================
--- openjpa/branches/2.3.x/openjpa-project/src/doc/manual/ref_guide_dbsetup.xml (original)
+++ openjpa/branches/2.3.x/openjpa-project/src/doc/manual/ref_guide_dbsetup.xml Thu May  1 03:10:56 2014
@@ -1405,9 +1405,36 @@ This value is usually one million, meani
 to store time values with a precision of one millisecond.  Particular
 databases may have more or less precision.
 OpenJPA will round all time values to this degree of precision
-before storing them in the database.
-Defaults to 1000000.
-                    </para>
+before storing them in the database.  This property can be set to one 
+of the following precisions:
+                </para>
+                <itemizedlist>
+                    <listitem>
+                        <para>
+<literal>DECI</literal>: 100000000
+                        </para>
+                    </listitem>
+                    <listitem>
+                        <para>
+<literal>CENIT</literal>: 10000000
+                        </para>
+                    </listitem>
+                    <listitem>
+                        <para>
+<literal>MILLI (default precision)</literal>: 1000000
+                        </para>
+                    </listitem>
+                    <listitem>
+                        <para>
+<literal>MICRO</literal>: 1000
+                        </para>
+                    </listitem>
+                    <listitem>
+                        <para>
+<literal>NANO (max precision)</literal>: 1
+                        </para>
+                    </listitem>
+                </itemizedlist>
                 </listitem>
                 <listitem id="DBDictionary.DateMillisecondBehavior">
                     <para>