Hazelcast 谓词/ SQL 查询类未找到

Posted

技术标签:

【中文标题】Hazelcast 谓词/ SQL 查询类未找到【英文标题】:Hazelcast Predicate/ SQL query class not found 【发布时间】:2021-11-22 22:44:04 【问题描述】:

我在 SQL 查询和谓词搜索中遇到类未找到异常,但不知道原因。

例外:

方法抛出 'com.hazelcast.nio.serialization.HazelcastSerializationException' 异常。 java.lang.ClassNotFoundException: com.mypackage.TestValue

Oct 01, 2021 10:57:14 AM com.hazelcast.map.impl.query.QueryPartitionOperation
SEVERE: [192.168.99.1]:5701 [nifi] [4.2.1] java.lang.ClassNotFoundException: com.mypackage.TestValue
com.hazelcast.nio.serialization.HazelcastSerializationException: java.lang.ClassNotFoundException: com.mypackage.TestValue
        at com.hazelcast.internal.serialization.impl.defaultserializers.JavaDefaultSerializers$JavaSerializer.read(JavaDefaultSerializers.java:90)
        at com.hazelcast.internal.serialization.impl.defaultserializers.JavaDefaultSerializers$JavaSerializer.read(JavaDefaultSerializers.java:79)
        at com.hazelcast.internal.serialization.impl.StreamSerializerAdapter.read(StreamSerializerAdapter.java:44)
        at com.hazelcast.internal.serialization.impl.AbstractSerializationService.toObject(AbstractSerializationService.java:208)
        at com.hazelcast.query.impl.CachedQueryEntry.getValue(CachedQueryEntry.java:98)
        at com.hazelcast.query.impl.CachedQueryEntry.getTargetObject(CachedQueryEntry.java:185)
        at com.hazelcast.query.impl.QueryableEntry.extractAttributeValue(QueryableEntry.java:108)
        at com.hazelcast.query.impl.QueryableEntry.getAttributeValue(QueryableEntry.java:62)
        at com.hazelcast.query.impl.predicates.AbstractPredicate.readAttributeValue(AbstractPredicate.java:145)
        at com.hazelcast.query.impl.predicates.AbstractPredicate.apply(AbstractPredicate.java:62)
        at com.hazelcast.query.impl.predicates.AndPredicate.apply(AndPredicate.java:136)
        at com.hazelcast.map.impl.query.PartitionScanRunner$1.accept(PartitionScanRunner.java:104)
        at com.hazelcast.map.impl.query.PartitionScanRunner$1.accept(PartitionScanRunner.java:89)
        at com.hazelcast.map.impl.recordstore.DefaultRecordStore.forEach(DefaultRecordStore.java:278)
        at com.hazelcast.map.impl.recordstore.DefaultRecordStore.forEach(DefaultRecordStore.java:261)
        at com.hazelcast.map.impl.recordstore.DefaultRecordStore.forEachAfterLoad(DefaultRecordStore.java:291)
        at com.hazelcast.map.impl.query.PartitionScanRunner.run(PartitionScanRunner.java:89)
        at com.hazelcast.map.impl.query.CallerRunsPartitionScanExecutor.execute(CallerRunsPartitionScanExecutor.java:43)
        at com.hazelcast.map.impl.query.QueryRunner.runPartitionIndexOrPartitionScanQueryOnGivenOwnedPartition(QueryRunner.java:236)
        at com.hazelcast.map.impl.query.QueryPartitionOperation.runInternal(QueryPartitionOperation.java:46)
        at com.hazelcast.map.impl.operation.MapOperation.run(MapOperation.java:115)
        at com.hazelcast.spi.impl.operationservice.Operation.call(Operation.java:189)
        at com.hazelcast.spi.impl.operationservice.impl.OperationRunnerImpl.call(OperationRunnerImpl.java:272)
        at com.hazelcast.spi.impl.operationservice.impl.OperationRunnerImpl.run(OperationRunnerImpl.java:248)
        at com.hazelcast.spi.impl.operationservice.impl.OperationRunnerImpl.run(OperationRunnerImpl.java:213)
        at com.hazelcast.spi.impl.operationexecutor.impl.OperationThread.process(OperationThread.java:175)
        at com.hazelcast.spi.impl.operationexecutor.impl.OperationThread.process(OperationThread.java:139)
        at com.hazelcast.spi.impl.operationexecutor.impl.OperationThread.executeRun(OperationThread.java:123)
        at com.hazelcast.internal.util.executor.HazelcastManagedThread.run(HazelcastManagedThread.java:102)
Caused by: java.lang.ClassNotFoundException: com.mypackage.TestValue
        at java.net.URLClassLoader.findClass(URLClassLoader.java:382)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:418)
        at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:355)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:351)
        at com.hazelcast.internal.nio.ClassLoaderUtil.tryLoadClass(ClassLoaderUtil.java:289)
        at com.hazelcast.internal.nio.ClassLoaderUtil.loadClass(ClassLoaderUtil.java:249)
        at com.hazelcast.internal.nio.IOUtil$ClassLoaderAwareObjectInputStream.resolveClass(IOUtil.java:910)
        at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1984)
        at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1848)
        at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2158)
        at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1665)
        at java.io.ObjectInputStream.readObject(ObjectInputStream.java:501)
        at java.io.ObjectInputStream.readObject(ObjectInputStream.java:459)
        at com.hazelcast.internal.serialization.impl.defaultserializers.JavaDefaultSerializers$JavaSerializer.read(JavaDefaultSerializers.java:86)
        ... 28 more

com.mypackage.HazelcastService:

Collection<HazelcastInstance> instances = HazelcastClient.getAllHazelcastClients();
Optional<HazelcastInstance> instance = instances.stream().findAny();
if (!instance.isPresent()) return;

IMap<String, TestValue> cacheMap = instance.get().getMap("test");
cacheMap.put("1", new TestValue(1, 1L));
cacheMap.put("2", new TestValue(2, 2L));
cacheMap.put("5", new TestValue(5, 5L));
cacheMap.put("9", new TestValue(9, 9L));

TestValue tv = cacheMap.get("1"); // works    
Collection<TestValue> values = cacheMap.values(); // works

Predicate<String, TestValue> gt = Predicates.greaterThan("testInt", 3);
Predicate<String, TestValue> lt = Predicates.lessThan("testInt", 7);
Predicate<String, TestValue> predicate = Predicates.and(gt, lt);
Collection<TestValue> testValues = cacheMap.values(predicate); // fails

SqlRow row = instance.get().getSql().execute("SELECT this FROM test WHERE testInt = 1").iterator().next(); // fails with whatever query I try

com.mypackage.TestValue 类很简单

public class TestValue implements Serializable 
    private static final long serialVersionUID = 333333L;
    private Integer testInt;
    private Long testLong;

    public TestValue(Integer testInt, Long testLong) 
        this.testInt = testInt;
        this.testLong = testLong;
    

    public TestValue() 
    

    public Integer getTestInt() 
        return testInt;
    

    public Long getTestLong() 
        return testLong;
    

    public void setTestInt(Integer testInt) 
        this.testInt = testInt;
    

    public void setTestLong(Long testLong) 
        this.testLong = testLong;
    

这只是本地环境,一切都在我的机器上运行,单个 Hazelcast 实例。 我的代码与官方文档中的示例相匹配。

Hazelcast 版本:4.2.1

Java 版本:1.8

【问题讨论】:

【参考方案1】:

您的代码如下:

Collection<HazelcastInstance> instances = HazelcastClient.getAllHazelcastClients();
Optional<HazelcastInstance> instance = instances.stream().findAny();

这意味着 Hazelcast 实例是一个客户端。因此,您必须有一个 Hazelcast 节点作为单独的进程运行。

问题是您的类在客户端是已知的,而不是在服务器端。由于您的查询是在服务器端运行的,因此您需要将您的类放在服务器类路径中,例如,当您启动它时,或者在 JSON 中序列化您的类,以便以不可知的方式对其进行查询。

【讨论】:

以上是关于Hazelcast 谓词/ SQL 查询类未找到的主要内容,如果未能解决你的问题,请参考以下文章

Oracle查询转换之连接谓词推入

IN 谓词在 SQL 中如何工作?

php中的SQL查询与数组中的谓词

使用 XPath 谓词优化 XQuery 查询

使用 like 谓词(模式匹配)对 DB2 Z/oS 的 SQL 查询进行性能调优

SQL 优化技术系列: 谓词下推