求助:BeanListHandler映射数据库Timestamp列获毫秒时间戳转存储格式
解决方案
首先明确:数据库的Timestamp类型本质存储的是毫秒级时间戳,并非字符串格式。你拿到的java.sql.Timestamp对象本身包含完整时间信息,只是默认输出为毫秒形式。要直接映射成yyyy-MM-dd HH:mm:ss.SSS格式的字符串,需要自定义Apache DbUtils的类型转换逻辑,具体实现如下:
方法1:自定义RowProcessor
将Bean中对应Timestamp列的字段类型改为String,通过自定义RowProcessor实现Timestamp到指定格式字符串的转换:
1. 实现自定义RowProcessor
import org.apache.commons.dbutils.BasicRowProcessor; import org.apache.commons.dbutils.RowProcessor; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Timestamp; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; public class CustomRowProcessor extends BasicRowProcessor { // Java 8+线程安全的日期格式化器 private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS"); @Override public Object processColumn(ResultSet rs, int index, Class<?> propType) throws SQLException { Object value = super.processColumn(rs, index, propType); // 当Bean字段为String,且数据库返回Timestamp时,格式化输出 if (value instanceof Timestamp && propType == String.class) { return DATE_FORMATTER.format(((Timestamp) value).toLocalDateTime()); } return value; } }
2. 使用自定义处理器
// 初始化自定义处理器 RowProcessor customProcessor = new CustomRowProcessor(); // 创建携带自定义处理器的BeanListHandler BeanListHandler<YourBean> handler = new BeanListHandler<>(YourBean.class, customProcessor); // 执行查询获取结果 List<YourBean> beanList = queryRunner.query(yourSqlStatement, handler);
方法2:自定义BeanProcessor
通过自定义BeanProcessor注册类型映射规则,更灵活控制数据库类型到Bean字段的转换:
1. 实现自定义BeanProcessor
import org.apache.commons.dbutils.BeanProcessor; import java.sql.Timestamp; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.HashMap; import java.util.Map; public class CustomBeanProcessor extends BeanProcessor { private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS"); public CustomBeanProcessor() { // 注册数据库TIMESTAMP类型到String的映射(不同数据库类型名可能有差异) super(getTypeMapping()); } private static Map<String, Class<?>> getTypeMapping() { Map<String, Class<?>> typeMap = new HashMap<>(); // MySQL用"TIMESTAMP",Oracle可能用"TIMESTAMP(3)",需根据实际调整 typeMap.put("TIMESTAMP", String.class); return typeMap; } @Override protected Object convert(Class<?> propType, Object value) throws SQLException { if (value instanceof Timestamp && propType == String.class) { return DATE_FORMATTER.format(((Timestamp) value).toLocalDateTime()); } return super.convert(propType, value); } }
2. 组合处理器并使用
// 初始化自定义BeanProcessor BeanProcessor beanProcessor = new CustomBeanProcessor(); // 创建包含自定义BeanProcessor的RowProcessor RowProcessor rowProcessor = new BasicRowProcessor(beanProcessor); // 创建BeanListHandler并执行查询 BeanListHandler<YourBean> handler = new BeanListHandler<>(YourBean.class, rowProcessor); List<YourBean> beanList = queryRunner.query(yourSqlStatement, handler);
注意事项
- 不同数据库的Timestamp类型名称可能不同,比如Oracle毫秒级Timestamp为
TIMESTAMP(3),需根据数据库类型调整getTypeMapping中的键值。 - 若使用Java 8以下版本,可替换为
SimpleDateFormat,但需注意它是非线程安全的,建议用ThreadLocal包裹避免并发问题。
内容的提问来源于stack exchange,提问作者Sijo Kurien
相关产品推荐
相关产品推荐

