Spring Boot+MyBatis中Timestamp转LocalDateTime失败问题求助
首先,咱们先拆解一下你遇到的错误:No constructor found in com.lisonn.mybatis.entity.Purchase matching [java.lang.Long, java.lang.String, java.lang.Integer, java.sql.Timestamp, java.lang.Integer]。这个错误的核心不是单纯的类型转换失败,而是MyBatis在尝试实例化Purchase对象时,找不到能匹配查询结果列类型的构造函数,而导致这个问题的根源有两个关键错误:
1. 误用<association>标签映射普通日期字段
你在PurchaseResultMap里用<association>来映射timing字段:
<association column="timing" property="timing" javaType="java.time.LocalDateTime"/>
这完全用错了标签!<association>是用来处理关联实体对象的(比如你的user字段,关联User实体),而timing是单个的日期值类型,应该用<result>标签。这种误用会让MyBatis错误地把timing列的Timestamp值当作一个关联对象来处理,打乱了类型转换逻辑,最终导致构造函数匹配失败。
2. 老版本MyBatis对Java 8时间类型的支持需要手动配置
你用的Spring Boot 1.5.9对应MyBatis Spring Boot Starter 1.3.1,底层的MyBatis核心版本是3.4.x,这个版本不会自动将JDBC的Timestamp转换为Java 8的LocalDateTime,必须手动指定对应的TypeHandler并正确配置。
具体修复步骤
步骤一:修正PurchaseResultMap的timing字段映射
把错误的<association>标签替换成<result>标签,并指定正确的TypeHandler:
<resultMap id="PurchaseResultMap" type="com.lisonn.mybatis.entity.Purchase"> <id column="id" property="id" /> <result column="naming" property="naming" /> <result column="price" property="price" /> <!-- 替换成正确的result标签,指定TypeHandler --> <result column="timing" property="timing" javaType="java.time.LocalDateTime" jdbcType="TIMESTAMP" typeHandler="org.apache.ibatis.type.LocalDateTimeTypeHandler"/> <association property="user" column="user_id" javaType="com.lisonn.mybatis.entity.User" select="selectUserForPurchase"/> </resultMap>
LocalDateTimeTypeHandler是MyBatis自带的Java 8时间类型处理器,MyBatis 3.4+已经包含这个类。
步骤二:确保Purchase实体类有正确的构造函数
MyBatis实例化对象有两种方式:
- 推荐方式:给Purchase类添加一个无参构造函数,并为所有字段提供setter方法。MyBatis默认会用无参构造创建对象,再通过setter注入字段值,这种方式最灵活,也能避免构造函数参数匹配的问题。
- 如果你想用构造函数注入,需要确保有一个参数类型完全匹配查询结果列的构造函数(比如
public Purchase(Long id, String naming, Integer price, LocalDateTime timing, Integer userId)),但这种方式不如无参构造+setter灵活。
步骤三:修正MyBatis配置的TypeHandler包路径
你的application.yaml里的type-handlers-package配置错了,正确的包名是org.apache.ibatis.type(因为LocalDateTimeTypeHandler在这个包下),修改后:
mybatis: mapper-locations: classpath:mappers/** type-aliases-package: com.lisonn.mybatis.entity # 修正TypeHandler的扫描包路径 type-handlers-package: org.apache.ibatis.type
这样MyBatis会自动扫描并注册所有自带的TypeHandler,包括处理Java 8时间类型的处理器。
步骤四:验证关联查询的映射
UserMapper里的selectUserPurchases引用了PurchaseResultMap,只要上面的ResultMap修复完成,关联查询的类型转换也会自动生效。
总结
你遇到的问题本质上是标签误用+老版本MyBatis的Java 8时间类型支持需要手动配置,导致MyBatis无法正确转换Timestamp到LocalDateTime,进而在实例化Purchase时找不到匹配的构造函数。按照上面的步骤修复后,应该就能解决这个问题了。
内容的提问来源于stack exchange,提问作者Vlad Hanzha

