JsonMappingException: No serializer found for class org.apache.ibatis.executor.loader.javassist.JavassistProxyFactory...

  |   0 评论   |   0 浏览

1.指定 <collection> 标签的 select,可以实现延迟加载,而且 SQL 也不会那么复杂,易读

<collection property="articles" column="article_id" fetchType="eager"
					ofType="com.jv.dynamic.bean.Article" select="queryArticleById">
		</collection>

2.直接在 <collection> 标签中写数据库字段与 Java 属性的映射关系

<collection property="articles" ofType="com.jv.dynamic.bean.Article">
			<id property="id" column="article_id"/>
			<result property="title" column="title"/>
			<result property="content" column="content"/>
			<result property="blogId" column="bid"/>
		</collection>

3.指定 <collection> 标签的 resultMap 属性,可以提高 resultMap 的重用率

<collection property="articles" ofType="com.jv.dynamic.bean.Article" resultMap="articleMap">
		</collection>
        <resultMap type="com.jv.dynamic.bean.Article" id="articleMap">
			<id property="id" column="article_id"/>
			<result property="title" column="title"/>
			<result property="content" column="content"/>
			<result property="blogId" column="bid"/>
        </resultMap>

我在项目中使用了第一种方式,数据读出来了,但是在 SpringMVC 返回的时候序列化报错

com.fasterxml.jackson.databind.JsonMappingException: No serializer found for class org.apache.ibatis.executor.loader.javassist.JavassistProxyFactory$EnhancedResultObjectProxyImpl and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) (through reference chain: java.util.ArrayList[0]->com.jv.dynamic.bean.Blog_$$_jvstd75_0["handler"])
	at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:275)
	at com.fasterxml.jackson.databind.SerializerProvider.mappingException(SerializerProvider.java:1109)
	at com.fasterxml.jackson.databind.SerializerProvider.reportMappingProblem(SerializerProvider.java:1134)
	at com.fasterxml.jackson.databind.ser.impl.UnknownSerializer.failForEmpty(UnknownSerializer.java:69)
	at com.fasterxml.jackson.databind.ser.impl.UnknownSerializer.serialize(UnknownSerializer.java:32)
	at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:693)
	at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:690)
	at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:155)
	at com.fasterxml.jackson.databind.ser.impl.IndexedListSerializer.serializeContents(IndexedListSerializer.java:119)
	at com.fasterxml.jackson.databind.ser.impl.IndexedListSerializer.serialize(IndexedListSerializer.java:79)
	at com.fasterxml.jackson.databind.ser.impl.IndexedListSerializer.serialize(IndexedListSerializer.java:18)
	at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:292)
	at com.fasterxml.jackson.databind.ObjectMapper._configAndWriteValue(ObjectMapper.java:3672)
	at com.fasterxml.jackson.databind.ObjectMapper.writeValueAsString(ObjectMapper.java:3048)
	at com.jv.test.TestBlog.test1(TestBlog.java:46)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:483)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
	at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
	at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:538)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:760)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:460)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:206)

在网上搜了很多,说这种错误可以使用@JsonIgnore @JsonIgnoreProperties 等方式解决,可试完所有我能找到的解决方法,依然不行。。。怎么办喃,慢慢 debug,一步一步缩小发生错误的范围,最终新建了一个普通 Java 工程用 jackson 来一点点序列化,突然发现打印出来的嵌套查询结果只有一行,但是真正的查询结果是有 6 行的,如果对 MyBatis 有一定了解的同学估计猜到原因了吧。。。对。。。就是我选择的嵌套查询方式默认是延迟加载的,我设置

<collection property="roleList" ofType="com.cloud.base.admin.api.entity.SysRole" fetchType="eager"
            select="com.cloud.base.admin.mapper.SysRoleMapper.listRolesByUserId" column="id">
</collection>

再测试,奇迹发生了。

所以在项目开发的时候,如果要使用第一种嵌套查询方式,那么对你的对象就需要认真考虑,如果不涉及到序列化,可以大胆使用它的延迟加载(fetchType="lazy"),否则就一次性加载完成(fetchType="eager"


标题:JsonMappingException: No serializer found for class org.apache.ibatis.executor.loader.javassist.JavassistProxyFactory...
作者:jockming112
地址:http://www.itwetouch.com/articles/2021/09/08/1631091502221.html