我正在使用PostgreSQL数据库,timestamp列有类java.sql.Timestamp。即使这个类扩展了java.util.Date,当我编辑PopupDateFiels时,我也获得了错误
无法将java.util.Date类型的值转换为模型类型类java.sql.Timestamp。没有设置转换器且类型不兼容。
默认转换器工厂无法正常工作。我试着写
dateField.setConverter(new DateToSqlDateConverter());
或
dateField.setConverter(StringToDateConverter.class);
结果相同。
通过点击日历中的某一天,我可以看到欧洲格式的有效日期和时间" 23.10.2014 13.44",但是在控制台上提交失败的类似消息:
Caused by: com.vaadin.data.util.converter.Converter$ConversionException: Could not convert value to Timestamp
at com.vaadin.ui.AbstractField.convertToModel(AbstractField.java:725)
at com.vaadin.ui.AbstractField.getConvertedValue(AbstractField.java:811)
at com.vaadin.ui.AbstractField.commit(AbstractField.java:247)
... 42 more
Caused by: com.vaadin.data.util.converter.Converter$ConversionException: Unable to convert value of type java.util.Date to model type class java.sql.Timestamp. No converter is set and the types are not compatible.
at com.vaadin.data.util.converter.ConverterUtil.convertToModel(ConverterUtil.java:181)
at com.vaadin.ui.AbstractField.convertToModel(AbstractField.java:745)
... 45 more
我在哪里可以得到合适的转换器?谢谢你的建议。
答案 0 :(得分:2)
我推荐这种方式:
PopupDateField pdf = new PopupDateField();
Timestamp ts = new Timestamp(System.currentTimeMillis());
ObjectProperty<Timestamp> prop = new ObjectProperty<Timestamp>(ts);
pdf.setPropertyDataSource(prop);
pdf.setConverter(MyConverter.INSTANCE);
使用此转换器:
public class MyConverter implements Converter<Date, Timestamp> {
private static final long serialVersionUID = 1L;
public static final MyConverter INSTANCE = new MyConverter();
@Override
public Timestamp convertToModel(Date value,
Class<? extends Timestamp> targetType, Locale locale)
throws ConversionException {
return value == null ? null : new Timestamp(value.getTime());
}
@Override
public Date convertToPresentation(Timestamp value,
Class<? extends Date> targetType, Locale locale)
throws ConversionException {
return new Date(value.getTime());
}
@Override
public Class<Timestamp> getModelType() {
return Timestamp.class;
}
@Override
public Class<Date> getPresentationType() {
return Date.class;
}
private Object readResolve() {
return INSTANCE; // preserves singleton property
}
}
答案 1 :(得分:0)
java.sql.Timestamp
视为java.util.Date
虽然java.sql.Timestamp
在技术上继承自java.util.Date
,但类doc的最后一段声明您不应该这样认为,您应该忽略这一事实。
由于Timestamp类和上面提到的java.util.Date类之间存在差异,因此建议代码不要将Timestamp值一般视为java.util.Date的实例。 Timestamp和java.util.Date之间的继承关系实际上表示实现继承,而不是类型继承。
换句话说,这个类结构是一个笨拙的黑客。早期Java中的日期时间类很匆忙,而且没有经过深思熟虑。
转换中的一个问题是java.sql.Timestamp具有纳秒分辨率,但java.util.Date只有毫秒,因此数据将丢失。
请注意,Vaadin使用支持网格的SQLContainer(可能是表格)犯了这个错误。 SQLContainer中的java.sql.Timestamp列被视为java.util.Date(超类),从而在涉及微秒或纳秒时丢失数据。 (请参阅下面的转换器实现作为解决方法。)
Java 8及更高版本中的新java.time package重新考虑了那些旧类,从头开始重新编写。这些新课程的灵感来自Joda-Time,由JSR 310定义,并由ThreeTen-Extra project扩展。
java.time类是为纳秒级分辨率而构建的。因此,在java.time.Instant和java.sql.Timestamp之间进行转换时不会丢失数据。
旧的和新的日期时间类都有在新旧之间来回转换的方法。请注意下面提到的java.sql.Timestamp::toInstant
和Timestamp.from( instant )
方法。
此示例可能有助于也可能无法回答问题。我正在将java.sql.Timestamp数据转换为java.time.Instant的字符串。
除了文本格式之外,请记住我的转换器和默认转换器之间存在一个大差异:没有数据丢失! (见上面的讨论)此示例屏幕截图发生,没有任何小数秒。但如果它确实有微秒或纳秒,那么该数据将被保留并显示为需要。
以下是一些代码,用于执行从java.sql.Timestamp转换的Instant
的String表示形式。换句话说:
此代码是根据与Vaadin 7捆绑在一起的source code类的com.vaadin.data.util.converter.StringToDateConverter
修改的。
此代码对我来说是在SQLContainer
中在Vaadin 7.5.2中显示Grid
对象的java.sql.Timestamp列。我还没有尝试Table
,但也应该在那里工作。
在为我工作时,此代码可能需要一些清理。特别是,(a)评论可能是错误的,(b)我有SLF4J日志记录,您可能需要更改/删除。
默认的ISO 8601格式对于人类来说有点难以阅读,因此我正在尝试更改格式和调整时区。
要使用此类,您必须在Grid.Column
对象上调用setConverter
。或按照ConverterFactory
。
package com.powerwrangler.util;
import com.vaadin.data.util.converter.Converter;
import java.text.DateFormat;
import java.time.format.DateTimeParseException;
import java.sql.Timestamp;
import java.util.Locale;
import java.time.Instant;
import org.slf4j.LoggerFactory;
/**
*
* Converts java.sql.Date objects for presentation as String in format of a java.time.Instant object.
*
* String format by default is DateTimeFormatter.ISO_INSTANT, such as '2011-12-03T10:15:30Z'.
*
* Based on code from Vaadin’s bundled StringToDateConverter.java
*
* PRESENTATION: String (of an Instant)
*
* MODEL: java.sql.Date
*
* @author Basil Bourque.
*
* This code is derived from the com.vaadin.data.util.converter.StringToDateConverter class bundled with Vaadin 7.
* That original class was published with this Copyright:
*
* Copyright 2000-2014 Vaadin Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*
*/
public class StringOfInstantToSqlTimestampConverter implements Converter<String , Timestamp>
{
// Member vars.
final org.slf4j.Logger logger = LoggerFactory.getLogger( this.getClass() );
/**
* Returns the format used by {@link #convertToPresentation(Date, Class,Locale)} and
* {@link #convertToModel(String, Class, Locale)}.
*
* @param locale The locale to use
*
* @return A DateFormat instance
*/
protected DateFormat getFormat ( Locale locale ) {
if ( locale == null ) {
locale = Locale.getDefault();
}
DateFormat f = DateFormat.getDateTimeInstance( DateFormat.MEDIUM , DateFormat.MEDIUM , locale );
f.setLenient( false );
return f;
}
/*
* (non-Javadoc)
*
* @see com.vaadin.data.util.converter.Converter#convertToModel(java.lang.Object, java.lang.Class, java.util.Locale)
*/
@Override
public Timestamp convertToModel ( String value , Class<? extends Timestamp> targetType , Locale locale )
throws com.vaadin.data.util.converter.Converter.ConversionException {
if ( targetType != getModelType() ) {
throw new Converter.ConversionException( "Converter only supports "
+ getModelType().getName() + " (targetType was "
+ targetType.getName() + ")" );
}
if ( value == null ) {
return null;
}
// Remove leading and trailing white space
String trimmed = value.trim();
// ParsePosition parsePosition = new ParsePosition( 0 );
// Date parsedValue = this.getFormat( locale ).parse( trimmed , parsePosition );
// if ( parsePosition.getIndex() != trimmed.length() ) {
// throw new Converter.ConversionException( "Could not convert '" + trimmed + "' to " + getModelType().getName() );
// }
Instant instant = null;
try {
instant = Instant.parse( trimmed ); // Uses DateTimeFormatter.ISO_INSTANT.
} catch ( DateTimeParseException e ) {
throw new Converter.ConversionException( "Could not convert '" + trimmed + "' to java.time.Instant on the way to get " + getModelType().getName() );
}
if ( instant == null ) {
logger.error( "The instant is null after parsing. Should not be possible. Message # ACE6DA4E-44C8-434C-A2AD-F946E5CFAEFD." );
throw new Converter.ConversionException( "The Instant is null after parsing while attempting to convert '" + trimmed + "' to java.time.Instant on the way to get " + getModelType().getName() + "Message # 77A767AB-7D42-490F-9C2F-2775F4443A8D." );
}
Timestamp parsedValue = Timestamp.from( instant );
return parsedValue;
}
/*
* (non-Javadoc)
*
* @see com.vaadin.data.util.converter.Converter#convertToPresentation(java.lang .Object, java.lang.Class,
* java.util.Locale)
*/
@Override
public String convertToPresentation ( Timestamp value , Class<? extends String> targetType , Locale locale )
throws com.vaadin.data.util.converter.Converter.ConversionException {
if ( value == null ) {
return null;
}
Instant instant = value.toInstant();
String dateTimeStringInIsoFormat = instant.toString(); // Uses DateTimeFormatter.ISO_INSTANT.
return dateTimeStringInIsoFormat;
//return getFormat( locale ).format( value );
}
/*
* (non-Javadoc)
*
* @see com.vaadin.data.util.converter.Converter#getModelType()
*/
@Override
public Class<Timestamp> getModelType () {
return Timestamp.class;
}
/*
* (non-Javadoc)
*
* @see com.vaadin.data.util.converter.Converter#getPresentationType()
*/
@Override
public Class<String> getPresentationType () {
return String.class;
}
}