Hazelcast使用Predicate与SQL查询时报TestValue类未找到异常
问题原因
普通get、全量values操作不需要Hazelcast服务端反序列化存储的对象,仅需将序列化后的二进制数据直接返回给客户端,由客户端完成反序列化,因此不会触发类加载逻辑。
而Predicate条件查询、SQL查询需要服务端根据对象属性做过滤判断,必须将存储的二进制数据反序列化为Java对象才能读取属性值,此时如果Hazelcast服务端的类路径下不存在com.mypackage.TestValue类,就会抛出ClassNotFoundException。
解决方案
方案1:将业务类部署到服务端(客户端-服务端部署架构适用)
如果你的Hazelcast是独立部署的集群节点,将包含com.mypackage.TestValue的jar包放到所有Hazelcast节点的lib/目录下,重启所有节点即可解决问题。
方案2:使用无类依赖的序列化方式(通用适用)
改用不需要服务端加载业务类的序列化方案,避免服务端反序列化时依赖业务类,可选方案包括:
- 使用Hazelcast自带的
IdentifiedDataSerializable、Portable序列化接口,这类序列化方式可直接读取属性值不需要加载完整类 - 使用
HazelcastJsonValue类型存储数据,服务端可直接解析JSON属性做过滤,完全不需要依赖业务类,示例代码如下:
// 存数据时转换为JSON类型 IMap<String, HazelcastJsonValue> cacheMap = instance.get().getMap("test"); cacheMap.put("1", new HazelcastJsonValue("{\"testInt\":1,\"testLong\":1}")); // 条件查询正常执行,服务端不需要TestValue类 Predicate<String, HazelcastJsonValue> gt = Predicates.greaterThan("testInt", 3); Collection<HazelcastJsonValue> testValues = cacheMap.values(gt); // 拿到结果后自行转换为TestValue对象即可
方案3:指定类加载器(嵌入式部署架构适用)
如果你的Hazelcast是嵌入式部署(和业务代码运行在同一个JVM进程中),可在初始化Hazelcast实例时指定使用业务上下文类加载器:
Config config = new Config(); config.setClassLoader(Thread.currentThread().getContextClassLoader()); HazelcastInstance instance = Hazelcast.newHazelcastInstance(config);
内容的提问来源于stack exchange,提问作者luka_roves
相关产品推荐
相关产品推荐

