MyBatis 关联查询和懒加载错误
今天在写项目时遇到了个BUG。先说一下背景,前端请求更新生产订单状态,后端从前端接收到生产订单ID进行查询,然后就有问题了。
先看控制台报错:
org.apache.ibatis.executor.ExecutorException: Statement returned more than one row, where no more than one was expected.
很明显,预期查出一条记录的结果查出了多条记录。因为在实现 service 层代码时直接返回的是 DAO 对象,而 DAO 是通过 MyBatis
实现的,因此直接对 DO 设计和 MyBatis 接口实现进行排查。
核心代码如下
DO类对象
//生产订单
public class ProduceDO extends AbstractDO implements Serializable {
//生产任务
private List<OrderProduceDO> orderProduceList;
}
接口实现
<resultMap id="ProduceDO" type="com.bootdo.erp.domain.ProduceDO">
<collection property="orderProduceList" select="com.bootdo.erp.dao.OrderProduceDao.list"
javaType="com.bootdo.erp.domain.OrderProduceDO"
column="{'produceId' = id}" fetchType="lazy">
</collection>
</resultMap>
<select id="get" resultMap="ProduceDO">
select `id`,`form_Id`,`proc_Ins_Id`,`number`,`type`,`start_time`,`end_time`,`create_by`,`create_time`,`remarks`,`status`,`del_flag` from erp_produce where id = #{value}
</select>
检查了一遍关联 DO 的代码实现,并且使用数据库直接进行数据查询,没找到问题。回看接口实现,发现关联属性 orderProduceList
的类型在 DO 里和 Mybatis 中不一致,将 javaType="com.bootdo.erp.domain.OrderProduceDO"
改为 javaType="java.utils.List"
或删除该行代码(Mybatis 已对 Java 常用类型进行了映射),运行,问题解决,nice!
but,再次运行,控制台又报了一个新错误:
org.springframework.http.converter.HttpMessageConversionException: Type definition error: [simple type, class org.apache.ibatis.executor.loader.javassist.JavassistProxyFactory E n h a n c e d R e s u l t O b j e c t P r o x y I m p l ] ; n e s t e d e x c e p t i o n i s c o m . f a s t e r x m l . j a c k s o n . d a t a b i n d . e x c . I n v a l i d D e f i n i t i o n E x c e p t i o n : N o s e r i a l i z e r f o u n d f o r c l a s s o r g . a p a c h e . i b a t i s . e x e c u t o r . l o a d e r . j a v a s s i s t . J a v a s s i s t P r o x y F a c t o r y EnhancedResultObjectProxyImpl]; nested exception is com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class org.apache.ibatis.executor.loader.javassist.JavassistProxyFactory EnhancedResultObjectProxyImpl];nestedexceptioniscom.fasterxml.jackson.databind.exc.InvalidDefinitionException:Noserializerfoundforclassorg.apache.ibatis.executor.loader.javassist.JavassistProxyFactoryEnhancedResultObjectProxyImpl and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) (through reference chain: com.bootdo.common.domain.R[“produce”]->com.bootdo.erp.domain.ProduceDO_$$_jvst156_0[“handler”])
黑人问号??? 虚假程序员打开百度,看到了这个 Mybatis懒加载——返回前端数据 json序列化错误,意思是错误是由懒加载导致的。
解决方法:在相关类上面加上 @JsonIgnoreProperties(value = { "handler"})
@JsonIgnoreProperties(value = { "handler"})
public class ProduceDO extends AbstractDO implements Serializable
@JsonIgnoreProperties(value = { "handler"})
public class OrderProduceDO extends AbstractDO implements Serializable
@JsonIgnoreProperties(value = { "handler"})
public abstract class AbstractDO implements Serializable {
再次运行,成功!
参考博客: