重写 BeanPropertyRowMapper 以支持 JodaTime DateTime
我的 Domain 对象有几个 Joda-Time DateTime
字段。当我使用 SimpleJdbcTemplate 读取数据库值时:
病人病人 = jdbc.queryForObject(sql, new BeanPropertyRowMapper(Patient.class), PatientId);
它只是失败了,令人惊讶的是,没有记录任何错误。我猜这是因为 timestamp
解析为 DateTime
不适用于 Jdbc。
如果可以继承并重写 BeanPropertyRowMapper 并指示将所有 java.sql.Timestamp 和 java.sql.Date 转换为 DateTime ,那就太好了,可以节省很多额外的代码。
有什么建议吗?
My Domain object has couple of Joda-Time DateTime
fields. When I'm reading database values using SimpleJdbcTemplate:
Patient patient = jdbc.queryForObject(sql, new
BeanPropertyRowMapper(Patient.class), patientId);
It just fails and surprisingly, no errors were logged. I guess it's because of the timestamp
parsing to DateTime
is not working with Jdbc.
If it's possible to inherit and override BeanPropertyRowMapper
and instruct to convert all java.sql.Timestamp
and java.sql.Date
to DateTime
, it would be great and could save a lot of extra code.
Any advice?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
正确的做法是子类化 BeanPropertyRowMapper,重写 initBeanWrapper(BeanWrapper) 并注册自定义属性编辑器:
The correct thing to do is to subclass
BeanPropertyRowMapper
, overrideinitBeanWrapper(BeanWrapper)
and register a custom Property Editor:查看 BeanPropertyRowMapper 实现,它设置字段的方式是:
其中 getColumnValue(rs, index, pd); 委托给 JdbcUtils.getResultSetValue
中的
pd
字段getColumnValue
是实际的“p Roperty d escriptor”,用于 (pd.getPropertyType()
)JdbcUtils
作为要映射到的字段的类型。如果您查看
getResultSetValue
方法的JdbcUtils
代码,您会发现它只是从一个if
语句转到另一个if
语句,以匹配>pd.getPropertyType()
到所有标准类型。当它找不到时,由于DateTime
不是“标准”类型,它依赖于rs.getObject()
:那么如果这个对象是一个SQL Date它将其转换为
Timestamp
,并返回以设置为您域的DateTime
字段 =>失败的地方。因此,似乎没有一种直接的方法可以将
Date
/Timestamp
到DateTime
转换器注入BeanPropertyRowMapper.因此,实现您自己的 RowMapper 会更干净(并且性能更高)。
如果您想在控制台中看到映射错误,请将
org.springframework.jdbc
的日志记录级别设置为“调试”或更好的“跟踪”以查看到底发生了什么。您可以尝试的一件事(我尚未测试过)是扩展 BeanPropertyRowMapper 并覆盖
DateTime
类型的属性:Looking at
BeanPropertyRowMapper
implementation, the way it sets the fields is:where
getColumnValue(rs, index, pd);
delegates to JdbcUtils.getResultSetValueThat
pd
field ingetColumnValue
is the actual "p roperty d escriptor", that is used (pd.getPropertyType()
) inJdbcUtils
as a type of the field to map to.If you look at
JdbcUtils
code forgetResultSetValue
method, you'll see that it simply goes from oneif
statement to another, to matchpd.getPropertyType()
to all standard types. When it does not find one, sinceDateTime
is not a "standard" type, it relies on ars.getObject()
:Then if this object is a SQL Date it converts it to a
Timestamp
, and returns to be set to aDateTime
field of your domain => where it fails.Hence, there does not seem to be a straight forward way to inject a
Date
/Timestamp
toDateTime
converter into aBeanPropertyRowMapper
. So it would be cleaner (and more performant) to implement your own RowMapper.In case you'd like to see the mapping error in a console, set your logging level for
org.springframework.jdbc
to "debug" or better yet "trace" to see exactly what happens.One thing you can try, which I have not tested, is to extend a
BeanPropertyRowMapper
and override a property ofDateTime
type in:@Sean Patrick Floyd 的答案是完美的,直到您没有很多自定义类型。
这是一个通用的、可根据使用情况配置的扩展:
The answer of @Sean Patrick Floyd is perfect until you do not have many many custom types.
Here it a generalized, configurable based on usage extension: