【发布时间】:2014-10-21 14:49:10
【问题描述】:
我正在使用 Postgres SQL 9.2、4.0.5 版的 Spring JDBC 和 Java 8。
Java 8 引入了新的日期/时间 API,我想使用它,但遇到了一些困难。
我已经创建了表 TABLE_A:
CREATE TABLE "TABLE_A"
(
new_date date,
old_date date
)
我正在使用 Spring JDBC 与数据库进行通信。我已经创建了 Java 类,对应这个表:
public class TableA
{
private LocalDate newDate;
private Date oldDate;
//getters and setters
}
这是我负责插入新行的代码:
public void create(TableA tableA)
{
BeanPropertySqlParameterSource parameterSource = new BeanPropertySqlParameterSource(tableA);
final String sql = "INSERT INTO public.TABLE_A (new_date,old_date) values(:newDate,:oldDate)";
namedJdbcTemplate.update(sql,parameterSource);
}
当我执行这个方法时,我得到了异常:
org.postgresql.util.PSQLException: Can't infer the SQL type to use for an instance of java.time.LocalDate. Use setObject() with an explicit Types value to specify the type to use.
所以我更新了 BeanPropertySqlParameterSource 的创建:
BeanPropertySqlParameterSource parameterSource = new BeanPropertySqlParameterSource(tableA);
parameterSource.registerSqlType("newDate", Types.DATE);
在那次更改之后,我能够插入行。但接下来,我想从数据库中获取行。这是我的方法:
public List<TableA> getAll()
{
final String sql = "select * from public.TABLE_A";
final BeanPropertyRowMapper<TableA> rowMapper = new BeanPropertyRowMapper<TableA>(TableA.class);
return namedJdbcTemplate.query(sql,rowMapper);
}
当然我有例外:
...
at org.springframework.beans.BeanWrapperImpl.convertIfNecessary(BeanWrapperImpl.java:474)
at org.springframework.beans.BeanWrapperImpl.convertForProperty(BeanWrapperImpl.java:511)
at org.springframework.beans.BeanWrapperImpl.setPropertyValue(BeanWrapperImpl.java:1119)
at org.springframework.beans.BeanWrapperImpl.setPropertyValue(BeanWrapperImpl.java:902)
at org.springframework.jdbc.core.BeanPropertyRowMapper.mapRow(BeanPropertyRowMapper.java:255)
...
Caused by: java.lang.IllegalStateException: Cannot convert value of type [java.sql.Date] to required type [java.time.LocalDate] for property 'newDate': no matching editors or conversion strategy found.
所以我更新了我的代码,这次是 BeanPropertyRowMapper,我为 bean wrapper 添加了转换服务,它能够执行从 java.sql.Date 到 java.time.LocalDate 的转换
public List<TableA> getAll()
{
final String sql = "select * from public.TABLE_A";
final BeanPropertyRowMapper<TableA> rowMapper = new BeanPropertyRowMapper<TableA>(TableA.class)
{
@Override
protected void initBeanWrapper(BeanWrapper bw) {
super.initBeanWrapper(bw);
bw.setConversionService(new ConversionService() {
@Override
public boolean canConvert(Class<?> aClass, Class<?> aClass2) {
return aClass == java.sql.Date.class && aClass2 == LocalDate.class;
}
@Override
public boolean canConvert(TypeDescriptor typeDescriptor, TypeDescriptor typeDescriptor2) {
return canConvert(typeDescriptor.getType(), typeDescriptor2.getType());
}
@Override
public <T> T convert(Object o, Class<T> tClass) {
if(o instanceof Date && tClass == LocalDate.class)
{
return (T)((Date)o).toLocalDate();
}
return null;
}
@Override
public Object convert(Object o, TypeDescriptor typeDescriptor, TypeDescriptor typeDescriptor2) {
return convert(o,typeDescriptor2.getType());
}
});
}
} ;
return namedJdbcTemplate.query(sql,rowMapper);
现在一切正常,但它相当复杂。
实现这一目标的方法是否更简单?
一般来说,我想在我的Java代码中对LocalDate进行操作,因为它更方便,并且可以持久化到数据库中。我希望它应该默认启用。
【问题讨论】:
标签: java spring postgresql java-8 spring-jdbc