You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openjpa.apache.org by jg...@apache.org on 2014/02/03 23:41:12 UTC
svn commit: r1564121 - in /openjpa/branches/2.3.x:
openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/
openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/temporal/
openjpa-project/src/doc/manual/
Author: jgrassel
Date: Mon Feb 3 22:41:12 2014
New Revision: 1564121
URL: http://svn.apache.org/r1564121
Log:
OPENJPA-2453: Add support to retain milliseconds of 'un-rounded' Date field.
Modified:
openjpa/branches/2.3.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionary.java
openjpa/branches/2.3.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/temporal/TestTemporalTimestamp.java
openjpa/branches/2.3.x/openjpa-project/src/doc/manual/ref_guide_dbsetup.xml
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=1564121&r1=1564120&r2=1564121&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 Mon Feb 3 22:41:12 2014
@@ -300,7 +300,31 @@ public class DBDictionary
public int maxEmbeddedClobSize = -1;
public int inClauseLimit = -1;
public int datePrecision = MILLI;
+
+ /**
+ * @deprecated Use 'dateMillisecondBehavior' instead.
+ */
+ @Deprecated
public boolean roundTimeToMillisec = true;
+
+ /*
+ * This defines how the milliseconds of a Date field are handled
+ * when the Date is retrieved from the database, as follows:
+ *
+ * ROUND: This is the default. The
+ * Date will be rounded to the nearest millisecond.
+ * DROP: The milliseconds will be dropped, thus rounding is not
+ * performed. As an example, a date of '2010-01-01 12:00:00.687701'
+ * stored in the database will become '2010-01-01 12:00:00.000' in
+ * the Date field of the entity.
+ * RETAIN: The milliseconds will not be rounded and retained. As an
+ * example, a date of '2010-01-01 12:00:00.687701' stored in the
+ * database will become '2010-01-01 12:00:00.687' in the Date field
+ * of the entity.
+ */
+ public enum DateMillisecondBehaviors { DROP, ROUND, RETAIN };
+ private DateMillisecondBehaviors dateMillisecondBehavior;
+
public int characterColumnSize = 255;
public String arrayTypeName = "ARRAY";
public String bigintTypeName = "BIGINT";
@@ -792,8 +816,16 @@ public class DBDictionary
// get the fractional seconds component, rounding away anything beyond
// milliseconds
int fractional = 0;
- if (roundTimeToMillisec) {
- fractional = (int) Math.round(tstamp.getNanos() / (double) MILLI);
+ switch (getMillisecondBehavior()) {
+ case DROP :
+ fractional = 0;
+ break;
+ case RETAIN :
+ fractional = (int) (tstamp.getNanos() / (double) MILLI);
+ break;
+ case ROUND :
+ fractional = (int) Math.round(tstamp.getNanos() / (double) MILLI);
+ break;
}
// get the millis component; some JDBC drivers round this to the
@@ -5621,6 +5653,33 @@ public class DBDictionary
public String getIdentityColumnName() {
return null;
+ }
+
+ /**
+ * Default behavior is ROUND
+ */
+ public DateMillisecondBehaviors getMillisecondBehavior() {
+ // If the user hasn't configured this property, fall back
+ // to looking at the old property in the mean time till
+ // we can get rid of it.
+ if (dateMillisecondBehavior == null) {
+ if (roundTimeToMillisec) {
+ dateMillisecondBehavior = DateMillisecondBehaviors.ROUND;
+ } else {
+ dateMillisecondBehavior = DateMillisecondBehaviors.DROP;
+ }
+ }
+ return dateMillisecondBehavior;
+ }
+
+ public void setDateMillisecondBehavior(String str) {
+ if (str != null) {
+ // Tolerate different case
+ str = str.toUpperCase();
+ dateMillisecondBehavior = DateMillisecondBehaviors.valueOf(str);
+ } else {
+ dateMillisecondBehavior = null;
+ }
}
protected boolean isUsingRange(long start, long end) {
Modified: openjpa/branches/2.3.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/temporal/TestTemporalTimestamp.java
URL: http://svn.apache.org/viewvc/openjpa/branches/2.3.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/temporal/TestTemporalTimestamp.java?rev=1564121&r1=1564120&r2=1564121&view=diff
==============================================================================
--- openjpa/branches/2.3.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/temporal/TestTemporalTimestamp.java (original)
+++ openjpa/branches/2.3.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/temporal/TestTemporalTimestamp.java Mon Feb 3 22:41:12 2014
@@ -18,6 +18,7 @@
*/
package org.apache.openjpa.persistence.temporal;
+import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
@@ -31,8 +32,8 @@ import org.apache.openjpa.persistence.Op
import org.apache.openjpa.persistence.test.SQLListenerTestCase;
public class TestTemporalTimestamp extends SQLListenerTestCase {
- private OpenJPAEntityManager em;
-
+ private OpenJPAEntityManager em;
+ final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
public void setUp() {
setSupportedDatabases(
@@ -42,8 +43,34 @@ public class TestTemporalTimestamp exten
return;
}
- setUp(CLEAR_TABLES, TemporalEntity.class, "openjpa.jdbc.DBDictionary", "RoundTimeToMillisec=false");
+ setUp(CLEAR_TABLES, TemporalEntity.class, "openjpa.jdbc.DBDictionary",
+ "DateMillisecondBehavior=" + DBDictionary.DateMillisecondBehaviors.DROP,
+ "openjpa.Log", "SQL=TRACE,Tests=TRACE", "openjpa.ConnectionFactoryProperties"
+ ,"PrintParameters=true");
assertNotNull(emf);
+// noRound:
+ // expected:<253402322399000> but was:<253402325999000>
+/* Date got = new Date(253402322399000L);
+ Date exp = new Date(253402325999000L);
+ System.out.println("NoRounding");
+ System.out.println("Got = " + sdf.format(got).toString());
+ System.out.println("Exp = " + sdf.format(exp).toString());
+*/
+ //testNoRoundingNoMillisecondLoss
+ //expected:<253402322399999> but was:<253402325999999>
+/* got = new Date(253402322399999L);
+ exp = new Date(253402325999999L);
+ System.out.println("testNoRoundingNoMillisecondLoss");
+ System.out.println("Got = " + sdf.format(got).toString());
+ System.out.println("Exp = " + sdf.format(exp).toString());
+ */
+ //expected:<253402322400000> but was:<253402326000000>
+/* got = new Date(253402322400000L);
+ exp = new Date(253402326000000L);
+ System.out.println("testRounding");
+ System.out.println("Got = " + sdf.format(got).toString());
+ System.out.println("Exp = " + sdf.format(exp).toString());
+ */
loadDB();
}
@@ -62,6 +89,32 @@ public class TestTemporalTimestamp exten
assertEquals(testDate.getMinutes(), 59);
assertEquals(testDate.getSeconds(), 59);
assertEquals(testDate.getYear(), 8099);
+ assertTrue(sdf.format(testDate).toString().endsWith(".000"));
+ }
+ em.close();
+ }
+
+ public void testNoRoundingNoMillisecondLoss() {
+ JDBCConfiguration conf = (JDBCConfiguration) emf.getConfiguration();
+ DBDictionary dict = conf.getDBDictionaryInstance();
+ dict.setDateMillisecondBehavior(DBDictionary.DateMillisecondBehaviors.RETAIN.toString());
+
+ em = emf.createEntityManager();
+ final List<TemporalEntity> temporalEntityList = findAll(em);
+ assertNotNull(temporalEntityList);
+ assertNotEquals(temporalEntityList.size(), 0);
+ for (final TemporalEntity temporalEntity : temporalEntityList) {
+ Date testDate = temporalEntity.getTestDate();
+ assertEquals(testDate.getDay(), 5);
+ assertEquals(testDate.getMonth(), 11);
+ assertEquals(testDate.getDate(), 31);
+ assertEquals(testDate.getHours(), 23);
+ assertEquals(testDate.getMinutes(), 59);
+ assertEquals(testDate.getSeconds(), 59);
+ assertEquals(testDate.getYear(), 8099);
+ assertTrue(sdf.format(testDate).toString().endsWith(".999"));
+ System.out.println("sdf.format(testDate).toString() = " +
+ sdf.format(testDate).toString());
}
em.close();
}
@@ -70,7 +123,7 @@ public class TestTemporalTimestamp exten
JDBCConfiguration conf = (JDBCConfiguration) emf.getConfiguration();
DBDictionary dict = conf.getDBDictionaryInstance();
// set value back to default
- dict.roundTimeToMillisec = true;
+ dict.setDateMillisecondBehavior(DBDictionary.DateMillisecondBehaviors.ROUND.toString());
em = emf.createEntityManager();
final List<TemporalEntity> temporalEntityList = findAll(em);
@@ -85,6 +138,8 @@ public class TestTemporalTimestamp exten
assertEquals(testDate.getMinutes(), 0);
assertEquals(testDate.getSeconds(), 0);
assertEquals(testDate.getYear(), 8100);
+// assertEquals(testDate.getTime(), 253402326000000L);
+ assertTrue(sdf.format(testDate).toString().endsWith(".000"));
}
em.close();
}
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=1564121&r1=1564120&r2=1564121&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 Mon Feb 3 22:41:12 2014
@@ -1409,6 +1409,53 @@ before storing them in the database.
Defaults to 1000000.
</para>
</listitem>
+ <listitem id="DBDictionary.DateMillisecondBehavior">
+ <para>
+ <indexterm>
+ <primary>
+ JDBC
+ </primary>
+ <secondary>
+ DateMillisecondBehavior
+ </secondary>
+ </indexterm>
+<literal>DateMillisecondBehavior</literal>:
+When retrieving a <literal>Date</literal> value from a database which stores the value in
+a TIMESTAMP column, the values retrieved will be rounded to the nearest
+millisecond. So a date of '2010-01-01 12:00:00.687701' stored in the
+database will become '2010-01-01 12:00:00.688' in the <literal>Date</literal> field of the
+entity. The following date stored in the database as '9999-12-31 23:59:59.9999'
+will become '10000-01-01 00:00:00.000'. This rounding may not be desirable. With this
+property, a user has options which will direct OpenJPA how to handle the milliseconds. This
+property can be set to one of the enums defined in
+<literal>DBDictionary.DateMillisecondBehaviors</literal>. The options defined in
+<literal>DBDictionary.DateMillisecondBehaviors</literal> are as follows:
+ <itemizedlist>
+ <listitem>
+ <para>
+<literal>DateMillisecondBehaviors.ROUND</literal>: This is the default. The
+<literal>Date</literal> will be rounded to the nearest millisecond, as described above.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+<literal>DateMillisecondBehaviors.DROP</literal>: The milliseconds will be dropped, thus
+rounding is not performed. As an example, a date of '2010-01-01 12:00:00.687701' stored in the
+database will become '2010-01-01 12:00:00.000' in the <literal>Date</literal> field of the
+entity.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+<literal>DateMillisecondBehaviors.RETAIN</literal>: The milliseconds will not be rounded, but will
+be retained. As an example, a date of '2010-01-01 12:00:00.687701' stored in the
+database will become '2010-01-01 12:00:00.687' in the <literal>Date</literal> field of the
+entity.
+ </para>
+ </listitem>
+ </itemizedlist>
+ </para>
+ </listitem>
<listitem id="DBDictionary.DateTypeName">
<para>
<indexterm>