From e9f3f9cdfcbb6479e02a477730debb320e5e5dbe Mon Sep 17 00:00:00 2001 From: Mark Struberg Date: Wed, 31 Mar 2021 19:09:03 +0200 Subject: [PATCH] OPENJPA-2883 fix handling of java.sql.Time on MSSQL --- .../openjpa/jdbc/sql/SQLServerDictionary.java | 27 +++++++++++++------ ...TestTemporalTypeQueryParameterBinding.java | 9 +++++++ openjpa-project/BUILDING.txt | 4 +-- pom.xml | 6 ++++- 4 files changed, 35 insertions(+), 11 deletions(-) diff --git a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SQLServerDictionary.java b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SQLServerDictionary.java index c50ccb126..a7061c47e 100644 --- a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SQLServerDictionary.java +++ b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SQLServerDictionary.java @@ -25,11 +25,13 @@ import java.sql.DatabaseMetaData; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; +import java.sql.Time; import java.sql.Types; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; import java.time.OffsetDateTime; +import java.util.Calendar; import java.util.Locale; import org.apache.openjpa.jdbc.identifier.DBIdentifier; @@ -61,13 +63,12 @@ public class SQLServerDictionary extends AbstractSQLServerDictionary { public boolean uniqueIdentifierAsVarbinary = true; /** - * Whether to send Time values as DateTime or as Time. - * This affects how the Database actually looks like. - * sendTimeAsDatetime is supported as of SQLServer2008 and - * is only to be used with TIME columns. - * Previous to that a DATETIME column had to be used with a fixed 1970-01-01 date. + * SQLServer doesn't like a java.sql.Time as default. + * So either we send it as String or people configure sendTimeAsDatetime=false on the Connection. + * This is depending how the Database actually is setup. + * To mitigate misconfiguration we can work around by sending the time as String to the JDBC driver. */ - public Boolean sendTimeAsDatetime = null; + public Boolean sendTimeAsString = null; public SQLServerDictionary() { platform = "Microsoft SQL Server"; @@ -95,8 +96,8 @@ public class SQLServerDictionary extends AbstractSQLServerDictionary { // serverMajorVersion of 8==2000, 9==2005, 10==2008, 11==2012 if (meta.getDatabaseMajorVersion() >= 9) { setSupportsXMLColumn(true); - if (sendTimeAsDatetime == null) { - sendTimeAsDatetime = Boolean.TRUE; + if (sendTimeAsString == null) { + sendTimeAsString = Boolean.FALSE; } } if (meta.getDatabaseMajorVersion() >= 10) { @@ -404,6 +405,16 @@ public class SQLServerDictionary extends AbstractSQLServerDictionary { return rs.getObject(column, OffsetDateTime.class); } + @Override + public void setTime(PreparedStatement stmnt, int idx, Time val, Calendar cal, Column col) throws SQLException { + if (sendTimeAsString) { + stmnt.setString(idx, val.toString()); + } + else { + // use Time + super.setTime(stmnt, idx, val, cal, col); + } + } @Override public void indexOf(SQLBuffer buf, FilterValue str, FilterValue find, diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/query/TestTemporalTypeQueryParameterBinding.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/query/TestTemporalTypeQueryParameterBinding.java index 90c9cbd1f..923c19d05 100644 --- a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/query/TestTemporalTypeQueryParameterBinding.java +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/query/TestTemporalTypeQueryParameterBinding.java @@ -133,6 +133,15 @@ public class TestTemporalTypeQueryParameterBinding extends SingleEMFTestCase { assertEquals(1, q.getResultList().size()); } + public void testNamedTimeParam() { + Date d2 = new Date(T2); + + Query q = em.createQuery("SELECT p FROM TimeKeeper p WHERE p.time=:t"); + q.setParameter("t", d2, TemporalType.TIME); + + assertEquals(1, q.getResultList().size()); + } + public void testPositionalParameterConvertedFromDateValue() { Date d1 = new Date(T1); Date d2 = new Date(T2); diff --git a/openjpa-project/BUILDING.txt b/openjpa-project/BUILDING.txt index 07358e245..e75d6cff4 100644 --- a/openjpa-project/BUILDING.txt +++ b/openjpa-project/BUILDING.txt @@ -212,8 +212,8 @@ For running against a h2 based installation: For running against a hsqldb based installation: -ea -Dopenjpa.ConnectionDriverName=org.hsqldb.Driver -Dopenjpa.ConnectionURL=jdbc:hsqldb:mem:openjpa20-hsqldb-database -Dopenjpa.ConnectionUserName=sa -Dopenjpa.ConnectionPassword= -For running tests against a SQLServer Docker based installation: - -ea -Dopenjpa.ConnectionDriverName=com.microsoft.sqlserver.jdbc.SQLServerDriver -Dopenjpa.ConnectionURL=jdbc:sqlserver://localhost:1433 -Dopenjpa.ConnectionUserName=SA -Dopenjpa.ConnectionPassword=OpenJP8tst +For running tests against a Microsoft SQLServer Docker based installation: + -ea -Dopenjpa.ConnectionDriverName=com.microsoft.sqlserver.jdbc.SQLServerDriver -Dopenjpa.ConnectionURL=jdbc:sqlserver://localhost:1433;sendTimeAsDatetime=false -Dopenjpa.ConnectionUserName=SA -Dopenjpa.ConnectionPassword=OpenJP8tst TODO: finish! diff --git a/pom.xml b/pom.xml index 0de9a01e0..583d793ba 100644 --- a/pom.xml +++ b/pom.xml @@ -947,7 +947,11 @@ openjpatst SA OpenJP8tst - jdbc:sqlserver://localhost:${docker.external.mssql.port} + + jdbc:sqlserver://localhost:${docker.external.mssql.port};sendTimeAsDatetime=false ${openjpa.mssql.url}