Java 使用BeanUtils.copyProperties时进行时区转换
我有一个Hibernate映射的模型类,如下所示Java 使用BeanUtils.copyProperties时进行时区转换,java,hibernate,timezone,date-conversion,apache-commons-beanutils,Java,Hibernate,Timezone,Date Conversion,Apache Commons Beanutils,我有一个Hibernate映射的模型类,如下所示 @Entity @Table(name = "USER") public class User implements Serializable { @Id @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "User_SEQ") @SequenceGenerator(sequenceName = "User_SEQ", allocationSi
@Entity
@Table(name = "USER")
public class User implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "User_SEQ")
@SequenceGenerator(sequenceName = "User_SEQ", allocationSize = 1, name = "User_SEQ")
private Integer id;
private Date createdOn;
}
@Test
public void testBeanUtilsDateConverter() throws Exception {
System.out.println("\ntestBeanUtilsDateConverter - Start");
Date date = new GregorianCalendar(2014, Calendar.FEBRUARY, 11, 18, 30, 10).getTime();
Date newDate = new Date();
DateConverter converter = new DateConverter();
converter.setTimeZone(TimeZone.getTimeZone("Europe/Copenhagen"));
BeanUtilsBean beanUtilsBean = BeanUtilsBean.getInstance();
beanUtilsBean.getConvertUtils().deregister(java.util.Date.class);
beanUtilsBean.getConvertUtils().register(converter, java.util.Date.class);
System.out.println(newDate);
BeanUtils.copyProperties(newDate, date);
System.out.println(date);
System.out.println(newDate);
System.out.println("testBeanUtilsDateConverter - End");
}
我有另一个模型类,如下所示,用于RESTAPI的响应。该类的对象本质上被序列化为JSON
public class UserDTO {
private Integer id;
private Date createdOn;
}
由于变量名相同,我使用BeanUtils.copyProperties将所有字段的值从User复制到UserDTO(为了简单起见,目前仅显示上面的2个字段)
数据以GMT格式存储在数据库中,因此createdOn字段包含GMT格式的时间戳。我想返回本地时区的日期,例如“欧洲/哥本哈根”。为此,我使用以下代码(使用apache commons)
代码已执行,但userDTO仍包含GMT格式的日期。时区转换不起作用。我错过了什么
编辑1:
我已尝试通过手动传递日期进行检查,如下所示
@Entity
@Table(name = "USER")
public class User implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "User_SEQ")
@SequenceGenerator(sequenceName = "User_SEQ", allocationSize = 1, name = "User_SEQ")
private Integer id;
private Date createdOn;
}
@Test
public void testBeanUtilsDateConverter() throws Exception {
System.out.println("\ntestBeanUtilsDateConverter - Start");
Date date = new GregorianCalendar(2014, Calendar.FEBRUARY, 11, 18, 30, 10).getTime();
Date newDate = new Date();
DateConverter converter = new DateConverter();
converter.setTimeZone(TimeZone.getTimeZone("Europe/Copenhagen"));
BeanUtilsBean beanUtilsBean = BeanUtilsBean.getInstance();
beanUtilsBean.getConvertUtils().deregister(java.util.Date.class);
beanUtilsBean.getConvertUtils().register(converter, java.util.Date.class);
System.out.println(newDate);
BeanUtils.copyProperties(newDate, date);
System.out.println(date);
System.out.println(newDate);
System.out.println("testBeanUtilsDateConverter - End");
}
输出:
testBeanUtilsDateConverter - Start
Fri Jun 02 14:04:08 IST 2017
Tue Feb 11 18:30:10 IST 2014
Tue Feb 11 18:30:10 IST 2014
testBeanUtilsDateConverter - End
testCustomDateConverter - Start
Instantiating MyDateConverter
Fri Jun 02 14:04:09 IST 2017
Tue Feb 11 18:30:10 IST 2014
Tue Feb 11 18:30:10 IST 2014
testCustomDateConverter - End
因此BeanUtils肯定是在将日期复制到目标,但是转换器要么没有被调用,要么由于某种原因没有执行任何操作
EDIT2-使用自定义转换器
class MyDateConverter implements Converter {
public MyDateConverter() {
System.out.println("Instantiating MyDateConverter");
}
@Override
public Object convert(Class Date, Object value) {
System.out.println("Inside convert()");
if (value == null) {
System.out.println("Value is null");
return (Date) null;
} else {
System.out.println("Doing date conversion");
Date date = new GregorianCalendar(2015, Calendar.JANUARY, 12, 9, 45, 15).getTime();
return date;
}
}
}
@Test
public void testCustomDateConverter() throws Exception {
System.out.println("\ntestCustomDateConverter - Start");
Date date = new GregorianCalendar(2014, Calendar.FEBRUARY, 11, 18, 30, 10).getTime();
Date newDate = new Date();
BeanUtilsBean beanUtilsBean = BeanUtilsBean.getInstance();
beanUtilsBean.getConvertUtils().deregister(java.util.Date.class);
beanUtilsBean.getConvertUtils().register(new MyDateConverter(), java.util.Date.class);
System.out.println(newDate);
BeanUtils.copyProperties(newDate, date);
System.out.println(date);
System.out.println(newDate);
System.out.println("testCustomDateConverter - End");
}
输出:
testBeanUtilsDateConverter - Start
Fri Jun 02 14:04:08 IST 2017
Tue Feb 11 18:30:10 IST 2014
Tue Feb 11 18:30:10 IST 2014
testBeanUtilsDateConverter - End
testCustomDateConverter - Start
Instantiating MyDateConverter
Fri Jun 02 14:04:09 IST 2017
Tue Feb 11 18:30:10 IST 2014
Tue Feb 11 18:30:10 IST 2014
testCustomDateConverter - End
同样的结果。自定义转换器正在实例化,但未调用convert方法。我甚至尝试了一个定制的长转换器来检查它是否与使用Date类有关,但即使这样也没有被调用。注册部分缺少BeanUtils无法调用重写的转换函数的内容。因此,如果我理解,您希望在数据库中以GMT格式存储日期。。。但是当用户访问数据时,它应该显示在他们自己的时区中?日期存储在数据库中的GMT中。用户向服务器发出RESTAPI调用,并在请求头中发送其时区和日期格式信息。服务器从数据库检索数据,并需要将日期转换为用户的时区,然后再将其作为JSON响应发送回用户。这是一种非常常见的情况。我本可以一个字段一个字段地复制,并使用SimpleDataFormat进行转换,但我想使用BeanUtils.copyProperties进行转换,以便由默认值完成。您是否手动测试了日期转换器?日期不包含时区(但这是一个常见的误解,因此请不要感到羞愧:-)虽然一个
GregorianCalendar
可以,但我要做的是切换到现代日期和时间类,并使用一个ZonedDateTime
。也许您甚至可以说服Hibernate将日期时间存储为另一个现代类Instant
。然后转换将非常简单(也可以进行日期转换)。其他选项,只需在User.createdOn
中存储为Instant
,并在向用户显示时仅格式化为哥本哈根时区。我想我会考虑一下这个清洁工。