我正在使用Postgres SQL 9.2,带有4.0.5版本的Spring JDBC和Java8。Java8
引入了新的日期/时间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包装器中,该服务能够执行从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进行操作,因为它更加方便,并且能够将其持久化到database
。我希望它应该默认启用。
JEP 170:JDBC 4.2定义了对JDBC的新的Date&Date
API支持。Postgres 下载页面与JDBC
4.2新功能的兼容性仅从Postgres 9.4版本开始,因此某些兼容性挑战将通过使用具有较旧驱动程序的新API弹出。
setObject(1, new java.util.Date());
在Postgres中,Even
被相同的约束所拒绝(MySQL很高兴地接受了它),不仅是新的API,如LocalDate
。有些行为将取决于实现,因此只能java.sql.*
保证(大致而言)。
至于Spring JDBC框架,我认为重写其行为可以绕过它,而不必以后再后悔。对于您已经做过的事情,我建议采取一种稍微不同的方法:
BeanPropertySqlParameterSource
行为以使用新的日期和时间API,以及在需要时与其他与参数输入相关联的类一起使用(我不熟悉该Spring API)。BeanPropertyRowMapper
到另一个类中以进行提取操作。这样,如果支持API,则可以增强将来的重构功能,并减少开发过程中所需的代码量。
您还可以查看一些DAO方法。
我是java.time包的新手。我有一个本地日期是2015-12-10。我需要将此转换为ZonedDateTime。时间应该是00:00:00,区域是zoneoffset.utc。 dateTimeException:无法从java.time.localDate类型的TemporalAccessor:2015-12-10获取Instant 我也试过: 这会产生意想不到的结果。 我查看了API并尝试
我在将时间戳对象转换为joda的LocalTime时遇到问题。 参见以下示例: 我无法确定为什么“new LocalDate(t)”会导致“1111-11-17”。有人能帮我吗? 在使用joda time hibernate填充bean的LocalDate类型属性时,我注意到了这个“问题”。
在Java8中,如何将(在中)转换为(在中)?
我有一个来自源代码的,根据规范,它应该是,但在类中没有看到任何方法将转换为。 最好的方法是什么?
在尝试将转换为时,我遇到以下异常。
问题内容: 有没有简单的方法可以将(Java 8中引入的)转换为对象? “简单”是指比这更简单: 对我来说似乎有点尴尬。 由于我们仅对日期部分感兴趣,并且两个对象都没有时区信息,因此为什么要明确引入时区?转换应隐式采用午夜时间和系统默认时区。 问题答案: 其实有。有一个静态方法的valueOf在这不正是那个对象。所以我们有 就是这样。没有明确设置时区,因为本地时区是隐式获取的。 从文档: 提供的L