如何在 Microstream 中正确使用 BinaryHandler 来存储 volatile 数组?
How to use BinaryHandler correctly in Microstream to store volatile array of longs?
我尝试使用 Microstream 存储 Eclipse Collection 的 LongArrayList (https://www.eclipse.org/collections/),但由于它的“项目”字段是瞬态的,所以无法立即使用。
所以我所做的是创建一个新的 class PersistableLongArrayList,如下所示:
public class PersistableLongArrayList extends LongArrayList {
static BinaryTypeHandler<PersistableLongArrayList> provideTypeHandler() {
return Binary.TypeHandler(PersistableLongArrayList.class,
Binary.Field_int(
"size",
list -> list.size,
(list, value) -> list.size = value
),
Binary.Field(
long[].class, "items",
list -> list.items,
(list, value) -> list.items = value
)
);
}
}
从存储的实例加载时,项目字段现在不为空,但是如果我之后更改值并调用 storage.store(list),关闭数据库并重新启动它,则不会存储新值,只有大小存储正确。
我添加了一个非常简单的示例来展示此行为:
public class SimpleTest {
private PersistableLongArrayList root;
public static void main(String[] args) {
try {
SimpleTest t = new SimpleTest();
// DB erstellen
EmbeddedStorageManager storage = t.startDB();
// modify the list
t.root.add(t.root.size() + 1);
storage.store(t.root);
// stop DB
t.stopDB(storage);
// restart DB
storage = t.startDB();
// show root element
System.out.println(t.root);
// Observed behavior: list "grows" from s.th. like this: [1] to s.th. like this [1, 0, 0, 0] after several runs (Probably only size grows and is stored correctly and therefore the fields up to "size" are printed but empty)
// Expected beahvior: list starts with [1] and grows to something like this [1, 2, 3, 4] after several runs
} catch (Throwable t) {
t.printStackTrace();
} finally {
System.exit(0);
}
}
private EmbeddedStorageManager startDB() {
EmbeddedStorageManager storageManager = EmbeddedStorage.start();
if(storageManager.root() == null) {
PersistableLongArrayList list = new PersistableLongArrayList();
storageManager.setRoot(list);
storageManager.storeRoot();
root = list;
} else {
root = (PersistableLongArrayList)storageManager.root();
}
return storageManager;
}
private void stopDB(EmbeddedStorageManager storageManager) {
storageManager.shutdown();
}
}
可能我只是误解了如何正确使用自定义 BinaryHandler,但我现在不知道要更改什么。
任何建议表示赞赏:)
亲切的问候,
托马斯
使用自定义 PersistenceEagerStoringFieldEvaluator 和 PersistenceFieldEvaluator 可以直接保存 LongArrayList:
public class PersistenceFieldEvaluatorCustom implements PersistenceFieldEvaluator {
@Override
public boolean applies(final Class<?> entityType, final Field field) {
//return true if field should be persisted, false if not
if(entityType == org.eclipse.collections.impl.list.mutable.primitive.LongArrayList.class && field.getName().equals("items")) {
return true;
}
//default: return false if field has the transient modifier
return !XReflect.isTransient(field);
}
}
public class PersistenceEagerStoringFieldEvaluatorCustom implements PersistenceEagerStoringFieldEvaluator {
@Override
public boolean isEagerStoring(final Class<?> t, final Field u) {
//return true if field should be persisted at every store
if(t == org.eclipse.collections.impl.list.mutable.primitive.LongArrayList.class && u.getName().equals("items")) {
return true;
}
return false;
}
}
设置:
final EmbeddedStorageManager s = EmbeddedStorage.Foundation()
.onConnectionFoundation(
c->{ c.setFieldEvaluatorPersistable(new PersistenceFieldEvaluatorCustom());
c.setReferenceFieldEagerEvaluator(new PersistenceEagerStoringFieldEvaluatorCustom());
})
.start();
此致
有关更多详细信息,请参阅 https://github.com/microstream-one/microstream/discussions/247
我尝试使用 Microstream 存储 Eclipse Collection 的 LongArrayList (https://www.eclipse.org/collections/),但由于它的“项目”字段是瞬态的,所以无法立即使用。
所以我所做的是创建一个新的 class PersistableLongArrayList,如下所示:
public class PersistableLongArrayList extends LongArrayList {
static BinaryTypeHandler<PersistableLongArrayList> provideTypeHandler() {
return Binary.TypeHandler(PersistableLongArrayList.class,
Binary.Field_int(
"size",
list -> list.size,
(list, value) -> list.size = value
),
Binary.Field(
long[].class, "items",
list -> list.items,
(list, value) -> list.items = value
)
);
}
}
从存储的实例加载时,项目字段现在不为空,但是如果我之后更改值并调用 storage.store(list),关闭数据库并重新启动它,则不会存储新值,只有大小存储正确。
我添加了一个非常简单的示例来展示此行为:
public class SimpleTest {
private PersistableLongArrayList root;
public static void main(String[] args) {
try {
SimpleTest t = new SimpleTest();
// DB erstellen
EmbeddedStorageManager storage = t.startDB();
// modify the list
t.root.add(t.root.size() + 1);
storage.store(t.root);
// stop DB
t.stopDB(storage);
// restart DB
storage = t.startDB();
// show root element
System.out.println(t.root);
// Observed behavior: list "grows" from s.th. like this: [1] to s.th. like this [1, 0, 0, 0] after several runs (Probably only size grows and is stored correctly and therefore the fields up to "size" are printed but empty)
// Expected beahvior: list starts with [1] and grows to something like this [1, 2, 3, 4] after several runs
} catch (Throwable t) {
t.printStackTrace();
} finally {
System.exit(0);
}
}
private EmbeddedStorageManager startDB() {
EmbeddedStorageManager storageManager = EmbeddedStorage.start();
if(storageManager.root() == null) {
PersistableLongArrayList list = new PersistableLongArrayList();
storageManager.setRoot(list);
storageManager.storeRoot();
root = list;
} else {
root = (PersistableLongArrayList)storageManager.root();
}
return storageManager;
}
private void stopDB(EmbeddedStorageManager storageManager) {
storageManager.shutdown();
}
}
可能我只是误解了如何正确使用自定义 BinaryHandler,但我现在不知道要更改什么。 任何建议表示赞赏:)
亲切的问候, 托马斯
使用自定义 PersistenceEagerStoringFieldEvaluator 和 PersistenceFieldEvaluator 可以直接保存 LongArrayList:
public class PersistenceFieldEvaluatorCustom implements PersistenceFieldEvaluator {
@Override
public boolean applies(final Class<?> entityType, final Field field) {
//return true if field should be persisted, false if not
if(entityType == org.eclipse.collections.impl.list.mutable.primitive.LongArrayList.class && field.getName().equals("items")) {
return true;
}
//default: return false if field has the transient modifier
return !XReflect.isTransient(field);
}
}
public class PersistenceEagerStoringFieldEvaluatorCustom implements PersistenceEagerStoringFieldEvaluator {
@Override
public boolean isEagerStoring(final Class<?> t, final Field u) {
//return true if field should be persisted at every store
if(t == org.eclipse.collections.impl.list.mutable.primitive.LongArrayList.class && u.getName().equals("items")) {
return true;
}
return false;
}
}
设置:
final EmbeddedStorageManager s = EmbeddedStorage.Foundation()
.onConnectionFoundation(
c->{ c.setFieldEvaluatorPersistable(new PersistenceFieldEvaluatorCustom());
c.setReferenceFieldEagerEvaluator(new PersistenceEagerStoringFieldEvaluatorCustom());
})
.start();
此致
有关更多详细信息,请参阅 https://github.com/microstream-one/microstream/discussions/247