ChronicleMap 自定义键和值序列化器

问题描述 投票:0回答:1

您好 ChronicleMap 用户,

我正在尝试将 ChronicleMap 与自定义键和值一起使用。 Key 由各种输入组成,Value 是数据库查找的结果。我想将其存储在内存中以加快后续请求的速度。然而,我正在努力决定键和值序列化器应该采用什么方法。这是我的 Key 和 Value,基本 Key 是 CacheKey,实现是 NetKey;我有几个不同的键可供使用。我尝试了几个选项,但似乎无法序列化/反序列化我的键/值。

public interface CacheKey extends Serializable {
    byte[] getKey();
    void setKey(Object object);
}

public interface CacheValue extends Serializable {
    byte[] getValue();
    void setValue(Object object);
}

@Builder
public class NetKey implements CacheKey {

    private String name;
    private String productType;
    private String dealDate;
    
    @Override
    public byte[] getKey() {
        return Util.writeToByte(this);
    }

    @Override
    public void setKey(Object object) {
        if (object instanceof NetKey) {
            NetKey o = (NetKey) object;
            this.name = o.name;
            this.productType = o.productType;
            this.dealDate = o.dealDate;
        }
    }

    //... override equals and hashCode
}

@Builder
public class NetValue implements CacheValue {

    private String entity;
    private String group;
    private Service service;

    @Override
    public byte[] getValue() {
        return Util.writeToByte(this);
    }

    @Override
    public void setValue(Object object) {
        if (object instanceof NetValue) {
            NetValue o = (NetValue) object;
            this.entity = o.entity;
            this.group = o.group;
            this.service = o.service;
        }
    }
 
    // override equals and hashCode
}

public class MyKeySerializer implements BytesReader<CacheKey>, BytesWriter<CacheKey> {

    private static MyKeySerializer INSTANCE = new MyKeySerializer();

    public static MyKeySerializer getInstance() { return INSTANCE; }

    private MyKeySerializer() {}

    @NotNull
    @Override
    public CacheKey read(Bytes in, @Nullable CacheKey using) {
        if (using == null) {
            using = new CacheKey() {
                @Override
                public CacheKey getKey() {
                    return this;
                }

                @Override
                public void setKey(CacheKey object) {

                }
            };
        }

        int len = in.readInt();
        Object object = Util.readFromByte(in.toByteArray());
        using.setKey(object == null ? null : (CacheKey) object);
        return using;
    }

    @Override
    public void write(Bytes out, @NotNull CacheKey toWrite) {
        byte[] content = Util.writeToByte(toWrite.getKey());
        out.writeInt(content.length);
        out.write(content);
    }

}

public class MyValueSerializer implements BytesReader<CacheValue>, BytesWriter<CacheValue> {

    private static MyValueSerializer INSTANCE = new MyValueSerializer();

    public static MyValueSerializer getInstance() { return INSTANCE; }

    private MyValueSerializer() {}

    @NotNull
    @Override
    public CacheValue read(Bytes in, @Nullable CacheValue using) {
        // TODO need help to implement this method
    }

    @Override
    public void write(Bytes out, @NotNull CacheValue toWrite) {
        // TODO need help to implement this method
    }

}

public class Test {
    
    public static void main(String[] args) {
        NetKey netKey = ...;
        NetValue netValue = ...;

        ChronicleMap<CacheKey, CacheValue> inMemoryMap = ChronicleMap.of(CacheKey.class, CacheKey.class)
           .name("sample-map")
           .entries(50)
           .averageKey(netKey)
           .averageValue(netValue)
           .keyMarshallers(MyKeySerializer.class)
           .valueMarshallers(MyValueSerializer.class)
           .create();
        inMemoryMap.put(netKey, netValue);
    }
}

更新1

我看到的错误是 StackOverflow

Exception in thread "main" java.lang.StackOverflowError
    at java.base/java.lang.RuntimeException.<init>(RuntimeException.java:52)
    at java.base/java.lang.IllegalArgumentException.<init>(IllegalArgumentException.java:40)
    at java.base/java.util.regex.PatternSyntaxException.<init>(PatternSyntaxException.java:58)
    at java.base/java.util.regex.Pattern.error(Pattern.java:2028)
    at java.base/java.util.regex.Pattern.<init>(Pattern.java:1432)
    at java.base/java.util.regex.Pattern.compile(Pattern.java:1069)
    at java.base/java.util.regex.Pattern.matches(Pattern.java:1174)
    at java.base/java.lang.String.matches(String.java:2839)
    at net.openhft.chronicle.values.CodeTemplate.lambda$null$20(CodeTemplate.java:206)
    at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:178)
    at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:179)
    at java.base/java.util.TreeMap$KeySpliterator.tryAdvance(TreeMap.java:3088)
    at java.base/java.util.stream.ReferencePipeline.forEachWithCancel(ReferencePipeline.java:129)
    at java.base/java.util.stream.AbstractPipeline.copyIntoWithCancel(AbstractPipeline.java:527)
    at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:513)
    at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
    at java.base/java.util.stream.FindOps$FindOp.evaluateSequential(FindOps.java:150)
    at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
    at java.base/java.util.stream.ReferencePipeline.findFirst(ReferencePipeline.java:647)
    at net.openhft.chronicle.values.CodeTemplate.lambda$methodsAndTemplatesByField$21(CodeTemplate.java:207)
    at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
    at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:179)
    at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:179)
    at java.base/java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:992)
    at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
    at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
    at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:921)
    at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
    at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:682)
    at net.openhft.chronicle.values.CodeTemplate.methodsAndTemplatesByField(CodeTemplate.java:214)
    at net.openhft.chronicle.values.CodeTemplate.createValueModel(CodeTemplate.java:104)
    at net.openhft.chronicle.values.ValueModel$1.computeValue(ValueModel.java:46)
    at java.base/java.lang.ClassValue.getFromHashMap(ClassValue.java:228)
    at java.base/java.lang.ClassValue.getFromBackup(ClassValue.java:210)
java spring-boot caching in-memory chronicle-map
1个回答
0
投票

我能够通过将键和值更改为 Class 并使用自定义序列化器来解决此问题。

@Getter
@Setter
@SuperBuilder
class NetKey extends CacheKey {
    private String productType;
    private String dealDate;

    @Override
    public boolean equals(Object object) {
        if (this == object) return true;
        if (object == null || getClass() != object.getClass()) return false;

        NetKey nk = (NetKey) object;
        return super.equals(object) &&
                (isEmpty(this.productType) || Objects.equals(this.productType, nk.productType)) &&
                Objects.equals(this.dealDate, nk.dealDate);
    }

    @Override
    public int hashCode() {
        return Objects.hash(super.hashCode(), productType, dealDate);
    }

    @Override
    public String toString() {
        return "NetKey{" +
                super.toString() +
                ", productType='" + productType + '\'' +
                ", dealDate='" + dealDate + '\'' +
                '}';
    }

}

@Setter
@Getter
@SuperBuilder
class CacheKey {
    private String cacheType;

    @Override
    public boolean equals(Object object) {
        if (this == object) return true;
        if (object == null || getClass() != object.getClass()) return false;

        CacheKey na = (CacheKey) object;
        return Objects.equals(this.cacheType, na.cacheType);
    }

    @Override
    public int hashCode() {
        return Objects.hash(cacheType);
    }

    @Override
    public String toString() {
        return "CacheKey{" +
                "cacheType='" + cacheType + '\'' +
                '}';
    }

}

@SuperBuilder
@Getter
@Setter
class NetValue extends CacheValue {
    private String entity;
    private String group;
    private String service;

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        NetValue that = (NetValue) o;
        return super.equals(o) &&
                Objects.equals(entity, that.entity) &&
                Objects.equals(group, that.group) &&
                Objects.equals(service, this.service);
    }

    @Override
    public int hashCode() {
        return Objects.hash(entity, group, service);
    }

    @Override
    public String toString() {
        return "NetValue{" +
                "entity='" + entity + '\'' +
                ", group='" + group + '\'' +
                ", service=" + service +
                '}';
    }

}

@SuperBuilder
@Getter
@Setter
class CacheValue {
    private String cacheType;

    @Override
    public boolean equals(Object object) {
        if (this == object) return true;
        if (object == null || getClass() != object.getClass()) return false;

        CacheValue na = (CacheValue) object;
        return Objects.equals(this.cacheType, na.cacheType);
    }

    @Override
    public int hashCode() {
        return Objects.hash(cacheType);
    }

    @Override
    public String toString() {
        return "CacheValue{" +
                "cacheType='" + cacheType + '\'' +
                '}';
    }

}

class CacheKeyMarshaller implements BytesReader<CacheKey>, BytesWriter<CacheKey> {

    public static CacheKeyMarshaller INSTANCE = new CacheKeyMarshaller();

    private CacheKeyMarshaller() {
    }

    @Override
    public CacheKey read(Bytes in, CacheKey using) throws IllegalStateException {
        String cacheType = in.readUtf8();

        CacheType cache = CacheType.valueOf(cacheType);
        if (cache == CacheType.NETTING) {
            return readNetKey(in, using, cacheType);
        } else {
            using = readCacheKey(in, using, cacheType);
        }

        return using;
    }

    @Override
    public void write(Bytes out, CacheKey toWrite) {
        CacheType cache = CacheType.valueOf(toWrite.getCacheType());
        if (cache == CacheType.NETTING) {
            writeNetKey(out, (NetKey) toWrite);
        } else {
            writeCacheKey(out, toWrite);
        }
    }

    private CacheKey readCacheKey(Bytes in, CacheKey using, String cacheType) {
        if (using == null) {
            using = CacheKey.builder().cacheType(cacheType).build();
        } else {
            using.setCacheType(cacheType);
        }
        return using;

    }

    private NetKey readNetKey(Bytes in, CacheKey using, String cacheType) {
        String productType = in.readUtf8();
        String dealDate = in.readUtf8();

        NetKey value;
        if (using == null) {
            value = NetKey.builder().cacheType(cacheType)
                    .productType(productType)
                    .dealDate(dealDate)
                    .build();
        } else {
            value = (NetKey) using;
            value.setCacheType(cacheType);
            value.setProductType(productType);
            value.setDealDate(dealDate);
        }
        return value;
    }

    private void writeCacheKey(Bytes out, CacheKey toWrite) {
        out.writeUtf8(toWrite.getCacheType());
    }

    private void writeNetKey(Bytes out, NetKey toWrite) {
        out.writeUtf8(toWrite.getCacheType());
        out.writeUtf8(toWrite.getProductType());
        out.writeUtf8(toWrite.getDealDate());
    }

}

class CacheValueMarshaller implements BytesReader<CacheValue>, BytesWriter<CacheValue> {

    public static CacheValueMarshaller INSTANCE = new CacheValueMarshaller();

    private CacheValueMarshaller() {
    }

    @Override
    public void write(Bytes out, CacheValue toWrite) {
        String cacheType = toWrite.getCacheType();

        CacheType cache = CacheType.valueOf(cacheType);
        if (cache == CacheType.NETTING) {
            writeNetValue(out, (NetValue) toWrite, cacheType);
        } else {
            writeCacheValue(out, toWrite);
        }
    }

    @Override
    public CacheValue read(Bytes in, CacheValue using) {
        String cacheType = in.readUtf8();

        CacheType cache = CacheType.valueOf(cacheType);
        if (cache == CacheType.NETTING) {
            return readNetValue(in, (NetValue) using, cacheType);
        } else {
            return readValueBase(in, using, cacheType);
        }
    }

    private NetValue readNetValue(Bytes in, NetValue using, String cacheType) {
        if (using == null) {
            using = NetValue.builder().cacheType(cacheType)
                    .entity(in.readUtf8())
                    .group(in.readUtf8())
                    .service(in.readUtf8())
                    .build();
        } else {
            using.setCacheType(cacheType);
            using.setEntity(in.readUtf8());
            using.setGroup(in.readUtf8());
            using.setService(in.readUtf8());
        }
        return using;
    }

    private CacheValue readValueBase(Bytes in, CacheValue using, String cacheType) {
        if (using == null) {
            using = CacheValue.builder().cacheType(cacheType).build();
        } else {
            using.setCacheType(cacheType);
        }
        return using;
    }

    private void writeNetValue(Bytes out, NetValue toWrite, String cacheType) {
        out.writeUtf8(cacheType);
        out.writeUtf8(toWrite.getEntity());
        out.writeUtf8(toWrite.getGroup());
        out.writeUtf8(toWrite.getService());
    }

    private void writeCacheValue(Bytes out, CacheValue toWrite) {
        out.writeUtf8(toWrite.getCacheType());
    }

}

public class Test {

    public static void main(String[] args) {
        ChronicleMap<CacheKey, CacheValue> map = null;
        try {
            NetKey key = NetKey.builder().cacheType(CacheType.NETTING.name())
                    .productType("type")
                    .dealDate("2023-04-23")
                    .build();

            NetValue value = NetValue.builder().cacheType(CacheType.NETTING.name())
                    .entity("entity")
                    .group("group")
                    .service("service")
                    .build();

            map = ChronicleMap.of(CacheKey.class, CacheValue.class)
                    .name("Sample-map")
                    .entries(50)
                    .averageKey(key)
                    .averageValue(value)
                    .keyMarshaller(CacheKeyMarshaller.INSTANCE)
                    .valueMarshaller(CacheValueMarshaller.INSTANCE)
                    .create();

            map.put(key, value);
            map.forEach((key1, value1) -> System.out.println(key1 + "->" + value1));
        } finally {
            if (map != null) map.close();
        }

    }

}
© www.soinside.com 2019 - 2024. All rights reserved.