Как временная метка SQL Server должна работать в JDBC? - PullRequest
1 голос
/ 02 ноября 2011

У меня возникли проблемы при попытке использовать timestamp2 вместо Timestamp в SQL Server 2008. По-видимому, rs.getTimestamp ведет себя очень по-разному между timestamp и timestamp2. Тем не менее, я не могу найти какую-либо документацию, утверждающую, что должна быть разница или что я должен использовать что-то другое. Интересно, я что-то не так делаю?

Окружающая среда:

  • Пробовал как на SQL Express 2008 (10.0), так и на SQL Server 2008 R2 (10.5).
  • sqljdbc4.jar версия 3.0, размер 537 303 байта, CRC-32 = a0aa1e25, MD5 = 402130141d5f2cee727f4371e2e8fd8a.
  • Java 1.6

Вот модульный тест, демонстрирующий проблему. Единственная «магия» - это «Db.getConnection ()», которую вы можете заменить соответствующим кодом. Тест одинаков как для datetime, так и для datetime2, но тест datetime2 завершается неудачно с датой за 2 дня. Я рассматриваю все время в БД как GMT / UTC, и я не пытался добавить информацию о часовом поясе в данные базы данных для данных datetime2.

    private void testTimestamp(TimeZone gmtTz, Connection conn, String query,
                    Calendar expectedCal) throws SQLException
    {
            PreparedStatement stmt = conn.prepareStatement(query);
            ResultSet rs = stmt.executeQuery();
            while (rs.next())
            {
                    // Note the expectedCal has a GMT timezone.
                    Date actualTs = rs.getTimestamp("dt", expectedCal);

                    // Just print out the time difference
                    long diff = actualTs.getTime() - expectedCal.getTimeInMillis();
                    System.out.println("Diff=" + diff);

                    // Do the test to make sure they are the same
                    // In practice, this succeeds for datetime and fails for datetime2
                    Assert.assertEquals(expectedCal.getTimeInMillis(), actualTs.getTime());
            }
    }

    @Test
    public void testDateTime() throws SQLException
    {
            Connection conn = Db.getConnection();
            TimeZone gmtTz = TimeZone.getTimeZone("GMT");
            String query;

            Calendar expectedCal = Calendar.getInstance(gmtTz);
            expectedCal.clear();
            expectedCal.set(2011, 10, 02, 11, 17);

            query = "select CAST('2011-11-02 11:17:00' as datetime) as dt";
            testTimestamp(gmtTz, conn, query, expectedCal);

            query = "select CAST('2011-11-02 11:17:00.0000000' as datetime2) as dt";
            testTimestamp(gmtTz, conn, query, expectedCal); // results in an error
    }

Мой единственный вариант - переключиться обратно на метку времени?

РЕДАКТИРОВАТЬ: Для будущих пользователей Google, использующих sqljdbc4.jar версии 3.0, тест не пройден в Linux, но пройден в Windows. Я еще не пробовал sqljdbc4.jar версии 4.0, которая поставляется с SQL Server 2012.

Ответы [ 2 ]

4 голосов
/ 20 апреля 2012

Если вы используете Sun JRE 1.7 с драйвером Microsoft JDBC 3.0, см. Этот блог http://blogs.msdn.com/b/jdbcteam/archive/2012/01/20/hotfix-available-for-date-issue-when-using-jre-1-7.aspx.

Если вы чувствуете, что обнаружили ошибку в нашем драйвере, вы можете сообщить о ней через Microsoft Connect.https://connect.microsoft.com/SQLServer

3 голосов
/ 03 ноября 2011

Я помню, что не слышал хороших слов о том, что предпочитают официальный драйвер SQL Server и JTDS (хотя я не могу найти эту ссылку).Я бы лично пошел с JTDS (конечно, с тщательным тестированием) или вернулся бы к версии, которая не вызывает проблем.Я не работал с SQL Server, но, судя по всему, datetime2 является предпочтительным типом данных, поэтому я бы не хотел возвращаться назад.Вариант (г) не очень хороший вариант ИМО.:)

...