Java microstream列表对象未正确存储
下面是扩展ArrayList的对象结构。当检索到该列表时,该列表为空,因此没有任何值存储在microstream对象图中。我也不确定这是不是真的Java microstream列表对象未正确存储,java,list,arraylist,microstream,Java,List,Arraylist,Microstream,下面是扩展ArrayList的对象结构。当检索到该列表时,该列表为空,因此没有任何值存储在microstream对象图中。我也不确定这是不是真的 虫子 不支持的功能 必须实现CustomHandler 创建FooTable对象和toString的代码将导致 FooTable(super=tablelistempl(super=[a,b,c],tableNo=1,datatableNo=2),baz=baz) 可在微束中储存。停止/启动app/DB并检索FooTable,列表为空。有趣的是,当检查
FooTable(super=tablelistempl(super=[a,b,c],tableNo=1,datatableNo=2),baz=baz)
可在微束中储存。停止/启动app/DB并检索FooTable,列表为空。有趣的是,当检查对象变量“size=3”时。
microstream似乎看不到该对象扩展列表的事实,只保留忽略列表的其他值
关于如何在不更改对象结构的情况下解决此问题的任何建议
注意:为了简洁起见,这里使用龙目山
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
@Getter
@Setter
@ToString(callSuper = true)
public class FooTable extends TableListImpl<String> {
public FooTable(int tableNo, int datatableNo) {
super(tableNo, datatableNo);
}
private static final long serialVersionUID = 1L;
private String baz;
}
这个问题其实不是一个bug。没有存储列表元素的事实是由java.util.ArrayList实现造成的,该实现将底层对象数组标记为瞬态。因此,Microstream默认情况下不会将其持久化。 但是自定义类型处理程序可以解决这个问题。 下面是FooTable类的此类类型处理程序的示例:
import one.microstream.X;
import one.microstream.persistence.binary.internal.AbstractBinaryHandlerCustomCollection;
import one.microstream.persistence.binary.types.Binary;
import one.microstream.persistence.types.PersistenceLoadHandler;
import one.microstream.persistence.types.PersistenceReferenceLoader;
import one.microstream.persistence.types.PersistenceStoreHandler;
public class FooTableTypeHandler extends AbstractBinaryHandlerCustomCollection<FooTable>
{
//the fields to be stored are:
//private final int tableNo from TableListImpl
//private final int datatableNo from TableListImpl;
//private String baz from FooTable
//transient Object[] elementData from ArrayList
//define the binary layout used for storing the class FooTable
private static final long BINARY_OFFSET_TABLE_NO = 0;
private static final long BINARY_OFFSET_DATA_TABLE_NO = BINARY_OFFSET_TABLE_NO + Integer.BYTES;
private static final long BINARY_OFFSET_BAZ = BINARY_OFFSET_DATA_TABLE_NO + Integer.BYTES;
private static final long BINARY_OFFSET_ELEMENTS = BINARY_OFFSET_BAZ + Binary.referenceBinaryLength(1);
protected FooTableTypeHandler()
{
super (FooTable.class,
SimpleArrayFields(
CustomField(int.class, "tableNo"),
CustomField(int.class, "datatableNo"),
CustomField(String.class, "baz")
)
);
}
@Override
public void iterateLoadableReferences(final Binary data, final PersistenceReferenceLoader iterator)
{
//register all referenced items that need to be restored too
data.iterateListElementReferences(BINARY_OFFSET_ELEMENTS, iterator);
iterator.acceptObjectId(data.read_long(BINARY_OFFSET_BAZ));
}
@Override
public void store(final Binary data, final FooTable instance, final long objectId, final PersistenceStoreHandler<Binary> handler)
{
//store items in the list
data.storeIterableAsList(
this.typeId() ,
objectId ,
BINARY_OFFSET_ELEMENTS,
instance ,
instance.size() ,
handler
);
//store int values directly
data.store_int(BINARY_OFFSET_TABLE_NO , instance.getTableNo());
data.store_int(BINARY_OFFSET_DATA_TABLE_NO, instance.getDatatableNo());
//store a reference to the String field "baz" and handle the String itself, if needed
data.store_long(BINARY_OFFSET_BAZ , handler.apply(instance.getBaz()));
}
@Override
public FooTable create(final Binary data, final PersistenceLoadHandler handler)
{
//read the int values
//create empty instance
return new FooTable(
data.read_int(BINARY_OFFSET_TABLE_NO),
data.read_int(BINARY_OFFSET_DATA_TABLE_NO));
}
private long getElementCount(final Binary data)
{
return data.getListElementCountReferences(BINARY_OFFSET_ELEMENTS);
}
@Override
public void updateState(final Binary data, final FooTable instance, final PersistenceLoadHandler handler)
{
// instance must be cleared in case an existing one is updated
instance.clear();
//get all list elements
data.collectObjectReferences(
BINARY_OFFSET_ELEMENTS,
X.checkArrayRange(this.getElementCount(data)),
handler,
e ->
instance.add((String) e)
);
//get "baz"
instance.setBaz((String) handler.lookupObject(data.read_long(BINARY_OFFSET_BAZ)));
}
}
导入一个.microstream.X;
导入一个.microsteam.persistence.binary.internal.AbstractBinaryHandlerCustomCollection;
导入一个.microsteam.persistence.binary.types.binary;
导入一个.microsteam.persistence.types.PersistenceLoadHandler;
导入一个.microsteam.persistence.types.PersistenceReferenceLoader;
导入一个.microsteam.persistence.types.PersistenceStoreHandler;
公共类FooTableTypeHandler扩展了AbstractBinaryHandlerCustomCollection
{
//要存储的字段包括:
//来自TableListImpl的私有最终int tableNo
//来自TableListImpl的私有最终int datatableNo;
//来自FooTable的私人字符串baz
//来自ArrayList的瞬态对象[]元素数据
//定义用于存储类FooTable的二进制布局
私有静态最终长二进制\u偏移量\u表\u编号=0;
私有静态最终长二进制\u偏移量\u数据\u表\u编号=二进制\u偏移量\u表\u编号+整数.BYTES;
私有静态最终长二进制_OFFSET_BAZ=二进制_OFFSET_DATA_TABLE_NO+Integer.BYTES;
私有静态最终长二进制偏移量元素=二进制偏移量+二进制。参考二进制长度(1);
受保护的FooTableTypeHandler()
{
超级(可脚踏级,
SimpleArrayFields(
自定义字段(int.class,“表号”),
CustomField(int.class,“datatableNo”),
CustomField(String.class,“baz”)
)
);
}
@凌驾
public void迭代器AdableReferences(最终二进制数据、最终持久化引用加载程序迭代器)
{
//同时注册所有需要恢复的引用项
iteratelistelementreference(二进制元素,迭代器);
acceptObjectId(data.read_long(二进制偏移量_BAZ));
}
@凌驾
公共void存储(最终二进制数据、最终FooTable实例、最终long objectId、最终PersistenceStoreHandler)
{
//在列表中存储项目
data.storeIterableAsList(
this.typeId(),
目标,
二进制偏移元素,
比如,,
instance.size(),
处理者
);
//直接存储int值
data.store_int(二进制_OFFSET_TABLE_NO,instance.getTableNo());
data.store_int(BINARY_OFFSET_data_TABLE_NO,instance.getDatatableNo());
//如果需要,存储对字符串字段“baz”的引用并处理字符串本身
data.store_long(BINARY_OFFSET_BAZ,handler.apply(instance.getBaz());
}
@凌驾
public FooTable create(最终二进制数据、最终PersistenceLoadHandler)
{
//读取int值
//创建空实例
返回新的脚踏板(
data.read_int(二进制偏移量表编号),
读取int(二进制偏移量数据表号);
}
私有长getElementCount(最终二进制数据)
{
返回数据.getListElementCountReferences(二进制元素);
}
@凌驾
public void updateState(最终二进制数据、最终FooTable实例、最终PersistenceLoadHandler)
{
//必须清除实例,以防更新现有实例
instance.clear();
//获取所有列表元素
data.collectObjectReferences(
二进制偏移元素,
X.checkArrayRange(this.getElementCount(数据)),
handler,
e->
add((字符串)e)
);
//获取“baz”
setBaz((String)handler.lookupObject(data.read_long(BINARY_OFFSET_BAZ));
}
}
这个问题其实不是一个bug。没有存储列表元素的事实是由java.util.ArrayList实现造成的,该实现将底层对象数组标记为瞬态。因此,Microstream默认情况下不会将其持久化。
但是自定义类型处理程序可以解决这个问题。
下面是FooTable类的此类类型处理程序的示例:
import one.microstream.X;
import one.microstream.persistence.binary.internal.AbstractBinaryHandlerCustomCollection;
import one.microstream.persistence.binary.types.Binary;
import one.microstream.persistence.types.PersistenceLoadHandler;
import one.microstream.persistence.types.PersistenceReferenceLoader;
import one.microstream.persistence.types.PersistenceStoreHandler;
public class FooTableTypeHandler extends AbstractBinaryHandlerCustomCollection<FooTable>
{
//the fields to be stored are:
//private final int tableNo from TableListImpl
//private final int datatableNo from TableListImpl;
//private String baz from FooTable
//transient Object[] elementData from ArrayList
//define the binary layout used for storing the class FooTable
private static final long BINARY_OFFSET_TABLE_NO = 0;
private static final long BINARY_OFFSET_DATA_TABLE_NO = BINARY_OFFSET_TABLE_NO + Integer.BYTES;
private static final long BINARY_OFFSET_BAZ = BINARY_OFFSET_DATA_TABLE_NO + Integer.BYTES;
private static final long BINARY_OFFSET_ELEMENTS = BINARY_OFFSET_BAZ + Binary.referenceBinaryLength(1);
protected FooTableTypeHandler()
{
super (FooTable.class,
SimpleArrayFields(
CustomField(int.class, "tableNo"),
CustomField(int.class, "datatableNo"),
CustomField(String.class, "baz")
)
);
}
@Override
public void iterateLoadableReferences(final Binary data, final PersistenceReferenceLoader iterator)
{
//register all referenced items that need to be restored too
data.iterateListElementReferences(BINARY_OFFSET_ELEMENTS, iterator);
iterator.acceptObjectId(data.read_long(BINARY_OFFSET_BAZ));
}
@Override
public void store(final Binary data, final FooTable instance, final long objectId, final PersistenceStoreHandler<Binary> handler)
{
//store items in the list
data.storeIterableAsList(
this.typeId() ,
objectId ,
BINARY_OFFSET_ELEMENTS,
instance ,
instance.size() ,
handler
);
//store int values directly
data.store_int(BINARY_OFFSET_TABLE_NO , instance.getTableNo());
data.store_int(BINARY_OFFSET_DATA_TABLE_NO, instance.getDatatableNo());
//store a reference to the String field "baz" and handle the String itself, if needed
data.store_long(BINARY_OFFSET_BAZ , handler.apply(instance.getBaz()));
}
@Override
public FooTable create(final Binary data, final PersistenceLoadHandler handler)
{
//read the int values
//create empty instance
return new FooTable(
data.read_int(BINARY_OFFSET_TABLE_NO),
data.read_int(BINARY_OFFSET_DATA_TABLE_NO));
}
private long getElementCount(final Binary data)
{
return data.getListElementCountReferences(BINARY_OFFSET_ELEMENTS);
}
@Override
public void updateState(final Binary data, final FooTable instance, final PersistenceLoadHandler handler)
{
// instance must be cleared in case an existing one is updated
instance.clear();
//get all list elements
data.collectObjectReferences(
BINARY_OFFSET_ELEMENTS,
X.checkArrayRange(this.getElementCount(data)),
handler,
e ->
instance.add((String) e)
);
//get "baz"
instance.setBaz((String) handler.lookupObject(data.read_long(BINARY_OFFSET_BAZ)));
}
}
导入一个.microstream.X;
导入一个.microsteam.persistence.binary.internal.AbstractBinaryHandlerCustomCollection;
导入一个.microsteam.persistence.binary.types.binary;
导入一个.microsteam.persistence.types.PersistenceLoadHandler;
导入一个.microsteam.persistence.types.PersistenceReferenceLoader;
导入一个.microsteam.persistence.types.PersistenceStoreHandler;
公共类FooTableTypeHandler扩展了AbstractBinaryHandlerCustomCollection
{
//要存储的字段包括:
//来自TableListImpl的私有最终int tableNo
//来自TableListImpl的私有最终int datatableNo;
import java.util.List;
public interface TableList<E> extends List<E>, Table {
}
public interface Table {
public int getTableNo();
public int getDatatableNo();
}
import one.microstream.X;
import one.microstream.persistence.binary.internal.AbstractBinaryHandlerCustomCollection;
import one.microstream.persistence.binary.types.Binary;
import one.microstream.persistence.types.PersistenceLoadHandler;
import one.microstream.persistence.types.PersistenceReferenceLoader;
import one.microstream.persistence.types.PersistenceStoreHandler;
public class FooTableTypeHandler extends AbstractBinaryHandlerCustomCollection<FooTable>
{
//the fields to be stored are:
//private final int tableNo from TableListImpl
//private final int datatableNo from TableListImpl;
//private String baz from FooTable
//transient Object[] elementData from ArrayList
//define the binary layout used for storing the class FooTable
private static final long BINARY_OFFSET_TABLE_NO = 0;
private static final long BINARY_OFFSET_DATA_TABLE_NO = BINARY_OFFSET_TABLE_NO + Integer.BYTES;
private static final long BINARY_OFFSET_BAZ = BINARY_OFFSET_DATA_TABLE_NO + Integer.BYTES;
private static final long BINARY_OFFSET_ELEMENTS = BINARY_OFFSET_BAZ + Binary.referenceBinaryLength(1);
protected FooTableTypeHandler()
{
super (FooTable.class,
SimpleArrayFields(
CustomField(int.class, "tableNo"),
CustomField(int.class, "datatableNo"),
CustomField(String.class, "baz")
)
);
}
@Override
public void iterateLoadableReferences(final Binary data, final PersistenceReferenceLoader iterator)
{
//register all referenced items that need to be restored too
data.iterateListElementReferences(BINARY_OFFSET_ELEMENTS, iterator);
iterator.acceptObjectId(data.read_long(BINARY_OFFSET_BAZ));
}
@Override
public void store(final Binary data, final FooTable instance, final long objectId, final PersistenceStoreHandler<Binary> handler)
{
//store items in the list
data.storeIterableAsList(
this.typeId() ,
objectId ,
BINARY_OFFSET_ELEMENTS,
instance ,
instance.size() ,
handler
);
//store int values directly
data.store_int(BINARY_OFFSET_TABLE_NO , instance.getTableNo());
data.store_int(BINARY_OFFSET_DATA_TABLE_NO, instance.getDatatableNo());
//store a reference to the String field "baz" and handle the String itself, if needed
data.store_long(BINARY_OFFSET_BAZ , handler.apply(instance.getBaz()));
}
@Override
public FooTable create(final Binary data, final PersistenceLoadHandler handler)
{
//read the int values
//create empty instance
return new FooTable(
data.read_int(BINARY_OFFSET_TABLE_NO),
data.read_int(BINARY_OFFSET_DATA_TABLE_NO));
}
private long getElementCount(final Binary data)
{
return data.getListElementCountReferences(BINARY_OFFSET_ELEMENTS);
}
@Override
public void updateState(final Binary data, final FooTable instance, final PersistenceLoadHandler handler)
{
// instance must be cleared in case an existing one is updated
instance.clear();
//get all list elements
data.collectObjectReferences(
BINARY_OFFSET_ELEMENTS,
X.checkArrayRange(this.getElementCount(data)),
handler,
e ->
instance.add((String) e)
);
//get "baz"
instance.setBaz((String) handler.lookupObject(data.read_long(BINARY_OFFSET_BAZ)));
}
}