近期在使用redis对数据进行缓存,通过Jackson将对象转换成字符串并保留类信息(@class),使用Jedis自定义实现Spring缓存逻辑。开发过程中发现,每当应用重启就会报:Could not resolve type id _$$_jvst as a subtype of `java.lang.Object`: no such class found。类没有找到。
<resultMap type="com.xxxxx.Abc" id="sabcResultMap"> <result property="id" column="id"/> <result property="code" column="code"/> <result property="type" column="type"/> <result property="fieldName" column="field_name"/> <result property="sort" column="sort"/> <result property="placeholder" column="placeholder"/> <result property="required" column="required"/> <collection property="abcConstraintList" javaType="java.util.ArrayList" column="id" ofType="com.xxxxx.AbcConstraint" select="com.xxxxx.AbcConstraintDAO.listByAbcId"/> </resultMap>
上面这段是mybatis的resultMap配置,查询的是一个resultMap,按照以往的思路和理解resultMap会映射成com.xxxx.Abc这个类的实例。
但查询结果其实是一个代理类,mybaits的命名规则为com.xxxx.Abc_$$_jvst12类似这样命名的类,而且每次重启应用后,下一次查询又是另一个名称的类。
{"@class":"com.xxxx.Abc_$$_jvst12","id":1001,"code":"test","type":"checkbox"}
所以如果查询结果先转换成JSON再缓存到redis中,然后在重启应用后,再次查询时先从缓存中获取出来的类信息@class是找不到的,并会抛出no such class found的异常。
如何解决此问题?在几经波折google无果后,我决定跟代码进行调试,发现这个动态生成的类是在org.apache.ibatis.executor.resultset.DefaultResultSetHandler的596行处理的,延迟加载导致的。
此时我回想hibernate的entity都是代理对象,都过代理实现延迟加载,恍然大悟。
直接修改mybatis配置文件,将lazyLoadingEnabled设置为false。
<setting name="lazyLoadingEnabled" value="false"/>
如果你想保留延迟加载,那这个方法不可行,或许你需要自定义Jackson的序列化逻辑,或者改变spring cache的缓存逻辑。
经测试,问题完美解决!