2015-06-04 2 views
1

Я пытаюсь создать предложение where с использованием поля datetime2 SQL Server (с точностью до 100 наносекунд); используя JPA & Hibernate.JPA усекает наносекунды при использовании критериев даты и SQL datetime2

Мой код выглядит примерно так:

CriteriaBuilder cb = em.getCriteriaBuilder(); 
List<Predicate> predicates = new ArrayList<>(); 
CriteriaQuery(X) q = cb.createQuery(X.class); 
Root<X> root = q.from(X.class); 

java.sql.Timestamp mySqlTimeStamp = Timestamp.valueOf("2015-06-04 11:31:53.2119339"); 

predicates.add(cb.greaterThan(root.get("DateModified"), mySqlTimeStamp)) 

q.where(predicates.toArray(new Predicate[predicates.size()])); 

em.createQuery(q).getResultList(); 

SQL Server Profiler показывает значение параметра метка времени усекается до 2015-06-04 11:31:53.210 - странно, что даже не округление. Иглы сказать, у меня есть неточности в результирующем наборе.

Если я вручную изменю параметр на полное значение 2015-06-04 11:31:53.2119339, все это хорошо.

Вопрос в том, как получить JPA до не усекать дату?

В качестве альтернативы, как вводить мое собственное значение сериализатора параметров для полей timestamp?

Справка оценена; благодаря

UPDATE я отслеживал его к этому jtds JDBC код: net.sourceforge.jtds.jdbc.JtdsPerparedStatement:

protected void setParameter(int parameterIndex, Object x, int targetSqlType, int scale, int length) 
     throws SQLException { 
     ParamInfo pi = getParameter(parameterIndex); 

     if ("ERROR".equals(Support.getJdbcTypeName(targetSqlType))) { 
      throw new SQLException(Messages.get("error.generic.badtype", 
           Integer.toString(targetSqlType)), "HY092"); 
     } 

     // Update parameter descriptor 
     if (targetSqlType == java.sql.Types.DECIMAL 
      || targetSqlType == java.sql.Types.NUMERIC) { 

      pi.precision = connection.getMaxPrecision(); 
      if (x instanceof BigDecimal) { 
       x = Support.normalizeBigDecimal((BigDecimal) x, pi.precision); 
       pi.scale = ((BigDecimal) x).scale(); 
      } else { 
       pi.scale = (scale < 0) ? TdsData.DEFAULT_SCALE : scale; 
      } 
     } else { 
      pi.scale = (scale < 0) ? 0 : scale; 
     } 

     if (x instanceof String) { 
      pi.length = ((String) x).length(); 
     } else if (x instanceof byte[]) { 
      pi.length = ((byte[]) x).length; 
     } else { 
      pi.length = length; 
     } 

     if (x instanceof Date) { 
      x = new DateTime((Date) x); 
     } else if (x instanceof Time) { 
      x = new DateTime((Time) x); 
     } else if (x instanceof Timestamp) { 
      x = new DateTime((Timestamp) x); 
     } 

     pi.value = x; 
     pi.jdbcType = targetSqlType; 
     pi.isSet = true; 
     pi.isUnicode = connection.getUseUnicode(); 
    } 
} 

Если метка время вынуждено net.sourceforge.jtds.jdbc.DateTime типа, который поддерживает только миллисекунду.

+0

Я думаю, вы имеете в виду "Timestamp.valueOf (...)" вместо нового. Я сделал аналогичную вещь, используя базу данных H2 и DataNucleus JPA, и мои наносы передаются в хранилище данных. Возможно, посмотрите, что Hibernate помещает в журнал и что делает драйвер SQLServer JDBC? –

+0

Да, valueOf() - Я скорректировал код. Я не передаю nanos, но обновляю и т. Д., Но я успешно их читаю, используя JPA. Получили ли вы успех с параметрами в критериях? – Gilbert

+0

Вы имеете в виду, в критерии выше, просто поместите cb.parameter, а затем вызовите setParameter в запросе (вместо использования литерала)? Да, это сработало для меня с H2 + DataNucleus –

ответ

0

Это более обходной путь; его то, что я сделал, чтобы решить проблему:

Как указано в обновлении вопроса, это были драйверы jtds, которые не поддерживают параметры datetime2. Я просто перешел на драйверы Microsoft - проблема решена.

Некоторые дополнительные идеи Обход:

  • Встраивание вызова Convert() функция, упаковка параметр буквальным; отправьте строковое значение Timestamp.
  • Fix jtds код - явно поддерживает JDBC NANOS
Смежные вопросы