【问题标题】:Store date and time from Java in SQL SERVER在 SQL SERVER 中存储来自 Java 的日期和时间
【发布时间】:2021-04-21 11:06:13
【问题描述】:

我正在尝试使用 SQL SERVER 中的 GregorianCalendar 类从 Java 存储日期时间,但它只存储日期。我需要在 SQL SERVER 中存储日期和时间。

这是我实现的代码

CallableStatement asignarTurno=conexionBBDD
                .getConexionBBDD().prepareCall("{call asignarTurno(?,?,?,?,?,?)}");
                
                //GregorianCalendar(int year, int month, int dayOfMonth, int hourOfDay, int minute, int second)
                
                GregorianCalendar h=new GregorianCalendar(2000, 1, 1, 8, 30,0);
                
                java.sql.Date date = new java.sql.Date(h.getTimeInMillis());
                 
                
                asignarTurno.setInt(1,1);
                asignarTurno.setDate(2,date);
                asignarTurno.setDate(3,date);
                asignarTurno.setDate(4,date);
                asignarTurno.setString(5, "000");
                asignarTurno.setString(6,"0001");
  
                
                asignarTurno.execute();
                
                  
            }
            catch (SQLException e) 
            {
                 
                e.printStackTrace();
            }
        }

【问题讨论】:

  • 列的数据类型是什么?
  • 列的数据类型是日期
  • 将详细信息发布为对问题的编辑,而不是评论。
  • @AriPaez 更改为日期时间。 docs.microsoft.com/en-us/sql/t-sql/data-types/…数据类型date只能存储日期部分
  • 顺便说一句。不要再使用过时的 Calendar-API。使用现代的java.time -API

标签: java sql sql-server


【解决方案1】:

您的代码存在多个问题。

永远不要使用糟糕的日期时间类,例如 GregorianCalendarDate。这些在几年前被 JSR 310 中定义的现代 java.time 类所取代。

您试图将具有日期、时间和隐式时区 (GregorianCalendar) 的时刻表示为假装只包含日期 (java.sql.Date) 的数据类型。方钉,圆孔。

仅限日期

Microsoft SQL Server 中的 DATE 类型类似于 SQL 标准类型 DATE,只包含一个日期,没有时间,也没有时区。所以在 Java 中使用java.time.LocalDate

LocalDate ld = LocalDate.of( 2000 , Month.FEBRUARY , 1 ) ;
myPreparedStatement.setObject( … , ld ) ;

和检索。

LocalDate ld = myResultSet.getObject( … , LocalDate.class ) ;

时刻

如果您确实想要跟踪时刻,则必须使用适当的data type 重新定义您的数据库列。在标准 SQL 中,这将是 TIMESTAMP WITH TIME ZONE。在 Microsoft SQL Server 中,这将是 datetimeoffset

在 Java 中,您可以将日期放在时区上下文中的时间。这会产生一个ZonedDateTime 对象。

LocalDate ld = LocalDate.of( 2000 , Month.FEBRUARY , 1 ) ;
LocalTime lt = LocalTime.of ( 8 , 30 ) ;
ZoneId z = ZoneId.of( "Africa/Tunis" ) ;
ZonedDateTime zdt = ZonedDateTime.of( ld , lt , z ) ;

不幸的是,JDBC 4.2 团队莫名其妙地决定需要支持OffsetDateTime,而不是两个更常用的类InstantZonedDateTime。因此,要获得最大的可移植代码,请使用OffsetDateTime。如果可移植性不是那么重要,请测试您的JDBC driver,看看它是否可选择支持ZonedDateTimeInstant

我们可以打电话给ZonedDateTime#toOffsetDateTime。但这会带来当时该时区使用的偏移量。为清楚起见,我建议改为调整为 UTC。这很容易通过从我们的ZonedDateTime 中提取Instant(始终为UTC)来完成。然后根据 JDBC 4.2 规范,我们使用offset of zero 转换为OffsetDateTime

OffsetDateTime odt = zdt.toInstant().atOffset( ZoneOffset.UTC ) ;

然后传递给你准备好的语句。

myPreparedStatement.setObject( … , odt ) ;

和检索。

OffsetDateTime odt = myResultSet.getObject( … , OffsetDateTime.class ) ;

关于java.time

java.time 框架内置于 Java 8 及更高版本中。这些类取代了麻烦的旧 legacy 日期时间类,例如 java.util.DateCalendarSimpleDateFormat

要了解更多信息,请参阅Oracle Tutorial。并在 Stack Overflow 上搜索许多示例和解释。规格为JSR 310

Joda-Time 项目现在位于maintenance mode,建议迁移到java.time 类。

您可以直接与您的数据库交换 java.time 对象。使用符合JDBC 4.2 或更高版本的JDBC driver。不需要字符串,不需要java.sql.* 类。 Hibernate 5 & JPA 2.2 支持 java.time

从哪里获取 java.time 类?

【讨论】:

    猜你喜欢
    • 2011-09-06
    • 1970-01-01
    • 1970-01-01
    • 2018-09-20
    • 2018-09-24
    • 1970-01-01
    • 1970-01-01
    • 2014-05-22
    • 1970-01-01
    相关资源
    最近更新 更多