如何创建自己的自定义谓词来比较榛子广播中的复合 id



我想创建自己的自定义谓词来比较复合ID的内部对象。需要是因为我必须在对象内部的对象(复合 id(上编写特定的日期比较逻辑。 我不想比较单个属性。我想使用复合 id,因为它来自调用程序,并且无法使用 Predicate.in 和谓词获得结果。

我的对象结构如下所示

Birth{id=BirthId{name='b3', dob=Wed Jan 01 10:53:20 IST 1902}, name='b3', dob=Wed Jan 01 10:53:20 IST 1902, description='MNP'}

在IMap内部,它的存储方式如下

key   : BirthId{name='b3', dob=Wed Jan 01 10:53:20 IST 1902}
value : Birth{id=BirthId{name='b3', dob=Wed Jan 01 10:53:20 IST 1902}, name='b3', dob=Wed Jan 01 10:53:20 IST 1902, description='MNP'}

我的Java类(出生和出生(结构如下

    public class Birth implements Serializable, Portable {
        private static final long serialVersionUID = 1L;
        private BirthId id;
        private String name;
        private Date dob;
        private String description;
        public BirthId getId() {
            return id;
        }
        public void setId(BirthId id) {
            this.id = id;
        }
        public String getDescription() {
            return description;
        }
        public void setDescription(String description) {
            this.description = description;
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public Date getDob() {
            return dob;
        }
        public void setDob(Date dob) {
            this.dob = dob;
        }
        public int hashCode() {
            return (new HashCodeBuilder()).append(this.id).append(this.name).append(this.dob).toHashCode();
        }
        public boolean equals(Object other) {
            if (other == this) {
                return true;
            } else if (!(other instanceof Birth)) {
                return false;
            } else {
                Birth rhs = (Birth) other;
                return (new EqualsBuilder()).append(this.id, rhs.id).append(this.name, rhs.name).append(this.dob, rhs.dob).isEquals();
            }
        }
        @Override public String toString() {
            return "Birth{" + "id=" + id + ", name='" + name + ''' + ", dob=" + dob + ", description='" + description + ''' + '}';
        }
        public int getFactoryId() {
            return 1;
        }
        public int getClassId() {
            return 1;
        }
        public void writePortable(PortableWriter portableWriter) throws IOException {
            portableWriter.writePortable("idComposite", getId());
            portableWriter.writeUTF("id", getId().toString());
            portableWriter.writeUTF("name", getName());
            portableWriter.writeUTF("description", getDescription());
            Date date = getDob();
            portableWriter.writeLong("dob", ((date == null) ? -1 : date.getTime()));
        }
        public void readPortable(PortableReader portableReader) throws IOException {
            setId((BirthId) portableReader.readPortable("idComposite"));
            setName(portableReader.readUTF("name"));
            setDescription(portableReader.readUTF("description"));
            long date = portableReader.readLong("dob");
            setDob(((date == -1) ? null : new Date(date)));
        }
    }
public class BirthId implements Comparable<BirthId>, Serializable, Portable {
    private static final long serialVersionUID = 1L;
    private String name;
    private Date dob;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Date getDob() {
        return dob;
    }
    public void setDob(Date dob) {
        this.dob = dob;
    }
    public int hashCode() {
        return (new HashCodeBuilder()).append(this.name).append(this.dob).toHashCode();
    }
    public boolean equals(Object other) {
        if (other == this) {
            return true;
        } else if (!(other instanceof BirthId)) {
            return false;
        } else {
            BirthId rhs = (BirthId) other;
            return (new EqualsBuilder()).append(this.name, rhs.name).append(this.dob, rhs.dob).isEquals();
        }
    }
    public int compareTo(BirthId rhs) {
        return this == rhs ? 0 : (null == rhs ? -1 : (new CompareToBuilder()).append(this.name, rhs.name).append(this.dob, rhs.dob).toComparison());
    }
    @Override public String toString() {
        return "BirthId{" + "name='" + name + ''' + ", dob=" + dob + '}';
    }
    public int getFactoryId() {
        return 1;
    }
    public int getClassId() {
        return 2;
    }
    public void writePortable(PortableWriter portableWriter) throws IOException {
        portableWriter.writeUTF("name", getName());
        Date date = getDob();
        portableWriter.writeLong("dob", ((date == null) ? -1 : date.getTime()));
    }
    public void readPortable(PortableReader portableReader) throws IOException {
        setName(portableReader.readUTF("name"));
        long date = portableReader.readLong("dob");
        setDob(((date == -1) ? null : new Date(date)));
    }
    public static ClassDefinition getClassDefinition(int portableVersion) {
        ClassDefinitionBuilder result = new ClassDefinitionBuilder(1, 2, portableVersion);
        result.addUTFField("name");
        result.addLongField("dob");
        return result.build();
    }
}

我创建了自己的自定义谓词来比较日期,如下所示

public class DatePredicate extends AbstractPredicate<Comparable, BirthId> {
    Comparable[] values;
    private volatile Set<Comparable> convertedInValues;
    public DatePredicate() {
    }
    public DatePredicate(String attribute, Comparable... values) {
        if (values == null) {
            throw new NullPointerException("Array can't be null");
        } else {
            this.values = values;
        }
    }
    protected boolean applyForSingleAttributeValue(Map.Entry entry, Comparable attributeValue) {
        //My own date comparison logic
        return true;
    }
    public int getId() {
        return 99;
    }
}

调用方代码是

Predicate p = new DatePredicate("id", new BirthId("12345",passSpecifiedDate()));
Result res = imap.values(p);

我得到以下错误

Exception in thread "main" com.hazelcast.nio.serialization.HazelcastSerializationException: com.hazelcast.internal.serialization.impl.ArrayDataSerializableFactory@5f007be3 is not be able to create an instance for id: 99 on factoryId: -32

我不知道创建自己的自定义谓词的最佳方法,并且 hazelcast 文档没有指定也。

任何人都可以指导我如何做到这一点吗?

@oomph-fortuity,你的DatePredicate扩展AbstractPredicate实现IdentifiedDataSerializable并由内置的Hazelcast谓词使用。内置谓词可序列化工厂尝试反序列化您的类并失败,因为它只知道如何序列化/反序列化内置谓词。

相反,只需实现com.hazelcast.query.Predicate接口:

class DatePredicate implements Predicate<BirthId, Birth> {
BirthId birthIdToCompare;
public DatePredicate() {
}
public DatePredicate(BirthId birthId) {
    this.birthIdToCompare = birthId;
}
@Override
public boolean apply(Map.Entry<BirthId, Birth> mapEntry) {
    BirthId key = mapEntry.getKey();
    ///your custom logic
    return true;
}
}

并像这样打电话

Predicate p = new DatePredicate(new BirthId("12345",passSpecifiedDate()));
Result res = imap.values(p);

让我知道这是否有效。

最新更新