我想从带有JDBC的Oracle DB表中获取DATETIME列。这是我的代码:
int columnType = rsmd.getColumnType(i);
if(columnType == Types.DATE)
{
Date aDate = rs.getDate(i);
valueToInsert = aDate.toString();
}
else if(columnType == Types.TIMESTAMP)
{
Timestamp aTimeStamp = rs.getTimestamp(i);
valueToInsert = aTimeStamp.toString();
}
else
{
valueToInsert = rs.getString(i);
}
我必须先识别列类型。我感兴趣的字段被识别为Types.DATE,但它实际上是数据库中的DATETIME,因为它具有以下格式:“07.05.2009 13:49:32”
getDate截断时间:“07.05.2009” 并且getString将“.0”附加到它:“07.05.2009 13:49:32.0”
当然我可以删除最终的.0并一直使用getString,但这是一个肮脏的解决方法。
有什么想法吗?我正在寻找一个getDateTime方法。
干杯, 添
答案 0 :(得分:83)
java.util.Date date;
Timestamp timestamp = resultSet.getTimestamp(i);
if (timestamp != null)
date = new java.util.Date(timestamp.getTime()));
然后按照您喜欢的方式对其进行格式化。
答案 1 :(得分:37)
answer by Leos Literak是正确的,但现在过时了,使用了一个麻烦的旧日期时间类java.sql.Timestamp
。
它实际上是数据库中的DATETIME
不,不是。 Oracle数据库中没有DATETIME
这样的数据类型。
我正在寻找一个getDateTime方法。
在JDBC 4.2及更高版本中使用 java.time 类,而不是在问题中看到麻烦的旧类。特别是,而不是java.sql.TIMESTAMP
,暂时使用Instant
类,例如SQL标准类型TIMESTAMP WITH TIME ZONE
。
受控代码段:
if(
JDBCType.valueOf(
myResultSetMetaData.getColumnType( … )
)
.equals( JDBCType.TIMESTAMP_WITH_TIMEZONE )
) {
Instant instant = myResultSet.getObject( … , Instant.class ) ;
}
我想从带有JDBC的Oracle DB表中获取DATETIME列。
根据this doc,Oracle数据库中没有列数据类型DATETIME
。这个术语似乎是Oracle的一句话,即将所有日期时间类型称为一个组。
我没有看到代码检测数据类型的类型和分支。通常,我认为您应该在特定表和特定业务问题的上下文中明确地制作代码。也许这在某种通用框架中很有用。如果您坚持,请继续阅读以了解各种类型,并了解Java 8及更高版本中内置的非常有用的新 java.time 类,它们取代了您的问题中使用的类。
valueToInsert = aDate.toString();
您似乎尝试将日期时间值与数据库作为文本交换为String
个对象。别。
要与数据库交换日期时间值,请使用日期时间对象。现在在Java 8及更高版本中,这意味着 java.time 对象,如下所述。
您可能会混淆三组与日期时间相关的数据类型:
SQL标准defines five types:
DATE
TIME WITHOUT TIME ZONE
TIME WITH TIME ZONE
TIMESTAMP WITHOUT TIME ZONE
TIMESTAMP WITH TIME ZONE
DATE
TIME
或TIME WITHOUT TIME ZONE
仅限时间,无日期。默认忽略指定为输入一部分的任何时区。TIME WITH TIME ZONE
(或TIMETZ
)TIMESTAMP
或TIMESTAMP WITHOUT TIME ZONE
TIMESTAMP WITH TIME ZONE
(或TIMESTAMPTZ
)许多数据库提供自己的日期时间相关类型。专有类型广泛地 。有些是旧的遗留类型,应该避免。有些人认为供应商提供某些好处;你决定是否坚持使用标准类型。注意:某些专有类型的名称与标准类型相冲突;我在看着你Oracle DATE
。
Java平台以不同于SQL标准或特定数据库的方式处理日期时间的内部细节。 JDBC driver的工作是在这些差异之间进行调解,充当桥梁,根据需要翻译类型及其实际实施的数据值。 java.sql.* package就是那座桥。
在Java 8之前,JDBC规范为日期时间工作定义了3种类型。前两个是版本8之前的黑客攻击,Java缺少任何类来表示仅限日期或仅限时间的值。
这样就可以回答你关于no" getDateTime"的问题。 ResultSet interface中的方法。该接口为JDBC中定义的三种桥接数据类型提供getter methods:
getDate
for java.sql.Date getTime
for java.sql.Time getTimestamp
for java.sql.Timestamp 请注意,第一个缺少任何时区概念或从UTC偏移。最后一个,java.sql.Timestamp
始终是UTC,尽管它的toString
方法告诉你。
您应该避免使用上面列出的设计糟糕的JDBC类。它们被 java.time 类型取代。
java.sql.Date
而不是LocalDate
。适合SQL标准DATE
类型。java.sql.Time
而不是LocalTime
。适合SQL标准TIME WITHOUT TIME ZONE
类型。java.sql.Timestamp
而不是Instant
。适合SQL标准TIMESTAMP WITH TIME ZONE
类型。 从JDBC 4.2及更高版本开始,您可以直接与数据库交换 java.time 对象。使用setObject
/ getObject
方法。
插入/更新。
myPreparedStatement.setObject( … , instant ) ;
检索。
Instant instant = myResultSet.getObject( … , Instant.class ) ;
Instant
类代表UTC中时间轴上的一个时刻,分辨率为nanoseconds(小数部分最多九(9)位)。
如果您希望通过特定区域(时区)的人使用的挂钟时间而不是UTC来查看Instant
的时刻,请通过应用{{1}进行调整获取ZoneId
对象。
ZonedDateTime
生成的ZoneId zAuckland = ZoneId.of( "Pacific/Auckland" ) ;
ZonedDateTime zdtAuckland = instant.atZone( zAuckland ) ;
对象是同一时刻,即时间轴上的同一点。新的一天早些时候在东方开始,所以日期和时间会有所不同。例如,新西兰午夜后的几分钟仍然是UTC的“昨天”。
您可以将另一个时区应用于ZonedDateTime
或Instant
,以便通过其他地区的人使用的另一个挂钟时间看到同一时刻。
ZonedDateTime
现在我们有三个对象(ZoneId zMontréal = ZoneId.of( "America/Montreal" ) ;
ZonedDateTime zdtMontréal = zdtAuckland.withZoneSameInstant( zMontréal ) ; // Or, for the same effect: instant.atZone( zMontréal )
,instant
,zdtAuckland
)都代表同一时刻,时间轴上的同一点。
回到有关检测数据库数据类型的问题中的代码:(a)不是我的专业领域,(b)如上所述我会避免这种情况,(c)如果你坚持这一点,请注意,从Java 8及更高版本开始,zMontréal
类已经过时了。该类现在由实现新接口Java Enum
的JDBCType
SQLType
替换。请参阅this Answer相关问题。
此更改列于JDBC Maintenance Release 4.2,第3和第3部分。 4.引用:
添加java.sql.JDBCType枚举
Enum用于标识通用SQL类型,称为JDBC类型。目的是使用JDBCType代替Types.java中定义的常量。
枚举与旧类具有相同的值,但现在提供type-safety。
关于语法的注释:在现代Java中,您可以在java.sql.Types
对象上使用switch
。因此,无需使用您的问题中所示的级联if-then语句。唯一的问题是,在切换某些模糊的技术原因时,必须使用enum对象的名称不合格,因此您必须在Enum
而不是合格的switch
上执行TIMESTAMP_WITH_TIMEZONE
。使用JDBCType.TIMESTAMP_WITH_TIMEZONE
声明。
所以,这就是说我猜(我还没有尝试过)你可以做类似下面的代码示例。
static import
java.time框架内置于Java 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,例如java.util.Date
,Calendar
和& SimpleDateFormat
现在位于Joda-Time的maintenance mode项目建议迁移到java.time类。
要了解详情,请参阅Oracle Tutorial。并搜索Stack Overflow以获取许多示例和解释。规范是JSR 310。
您可以直接与数据库交换 java.time 对象。使用符合JDBC driver或更高版本的JDBC 4.2。不需要字符串,不需要final int columnType = myResultSetMetaData.getColumnType( … ) ;
final JDBCType jdbcType = JDBCType.valueOf( columnType ) ;
switch( jdbcType ) {
case DATE : // FYI: Qualified type name `JDBCType.DATE` not allowed in a switch, because of an obscure technical issue. Use a `static import` statement.
…
break ;
case TIMESTAMP_WITH_TIMEZONE :
…
break ;
default :
…
break ;
}
类。
从哪里获取java.time类?
ThreeTen-Extra项目使用其他类扩展java.time。该项目是未来可能添加到java.time的试验场。您可以在此处找到一些有用的课程,例如Interval
,YearWeek
,YearQuarter
和more。
更新:现在位于Joda-Time的maintenance mode项目建议迁移到java.time课程。这部分原封不动。
在Java 8(java.time。*包)之前,与java捆绑的日期时间类(java.util.Date&amp; Calendar,java.text.SimpleDateFormat)出了名的麻烦,令人困惑和有缺陷。< / p>
更好的做法是获取JDBC驱动程序为您提供的内容以及创建Joda-Time对象或Java 8中的java.time.* package。最终,您应该看到自动使用新的java.time。*类的新JDBC驱动程序。在此之前,已经在java.sql.Timestamp等类中添加了一些方法来插入java.time,例如toInstant
和java.sql.*
。
至于问题的后半部分,渲染String ...应该使用格式化程序对象来生成字符串值。
老式的方法是使用java.text.SimpleDateFormat。不推荐。
Joda-Time提供各种内置格式化程序,您也可以定义自己的格式化程序。但是,如您所述,为了编写日志或报告,最佳选择可能是ISO 8601格式。该格式恰好是Joda-Time和java.time。
使用的默认格式
fromInstant
转储到控制台...
//java.sql.Timestamp timestamp = resultSet.getTimestamp(i);
// Or, fake it
// long m = DateTime.now().getMillis();
// java.sql.Timestamp timestamp = new java.sql.Timestamp( m );
//DateTime dateTimeUtc = new DateTime( timestamp.getTime(), DateTimeZone.UTC );
DateTime dateTimeUtc = new DateTime( DateTimeZone.UTC ); // Defaults to now, this moment.
// Convert as needed for presentation to user in local time zone.
DateTimeZone timeZone = DateTimeZone.forID("Europe/Paris");
DateTime dateTimeZoned = dateTimeUtc.toDateTime( timeZone );
跑步时......
System.out.println( "dateTimeUtc: " + dateTimeUtc );
System.out.println( "dateTimeZoned: " + dateTimeZoned );
答案 2 :(得分:0)
这有效:
Date date = null;
String dateStr = rs.getString("doc_date");
if (dateStr != null) {
date = dateFormat.parse(dateStr);
}
使用SimpleDateFormat。
答案 3 :(得分:0)
我选择的解决方案是使用mysql查询格式化日期:
String l_mysqlQuery = "SELECT DATE_FORMAT(time, '%Y-%m-%d %H:%i:%s') FROM uld_departure;"
l_importedTable = fStatement.executeQuery( l_mysqlQuery );
System.out.println(l_importedTable.getString( timeIndex));
我有完全相同的问题。
即使我的mysql表包含格式如下的日期:2017-01-01 21:02:50
String l_mysqlQuery = "SELECT time FROM uld_departure;"
l_importedTable = fStatement.executeQuery( l_mysqlQuery );
System.out.println(l_importedTable.getString( timeIndex));
返回格式如下的日期:
2017-01-01 21:02:50.0