将 null 存储为实体 属性 的值?
Storing null as value of Entity Property?
由于实体存储在存储空值时抛出,我设法得到一个 "hack" 来将空值保存到其中。但是我不确定我的方法是否徒劳。
这是一个片段:
entityStore.executeInTransaction(new StoreTransactionalExecutable() {
@Override
public void execute(@NotNull final StoreTransaction txn) {
try {
entityStore.registerCustomPropertyType(txn, UndefinedIterable.class, UndefinedBinding.BINDING);
} catch (Exception e) {
}
final Entity entity = txn.newEntity(storeName);
Iterator<String> it = comparableMap.keySet().iterator();
while (it.hasNext()) {
String key = it.next();
Comparable value = comparableMap.get(key);
if(value == null) {
entity.setProperty(key, new UndefinedIterable());
} else {
entity.setProperty(key, value);
}
}
这里的第一个问题是,一遍又一遍地 registerCustomPropertyType
是否安全,因为每次服务器收到 POST 请求时都会调用此方法。
接下来这里还需要UndefinedIterable
吗?
完整代码如下
UndefinedIterable.java
public class UndefinedIterable implements Serializable, ByteIterable {
private byte[] bytes;
public UndefinedIterable() {
bytes = "null".getBytes();
}
@Override
public ByteIterator iterator() {
return new ArrayByteIterable(bytes).iterator();
}
@Override
public byte[] getBytesUnsafe() {
return bytes;
}
@Override
public int getLength() {
return bytes.length;
}
@NotNull
@Override
public ByteIterable subIterable(int offset, int length) {
return null;
}
@Override
public int compareTo(@NotNull ByteIterable o) {
return 0;
}
}
UndefinedBinding.java
public class UndefinedBinding extends ComparableBinding {
public static final UndefinedBinding BINDING = new UndefinedBinding();
@Override
public Comparable readObject(@NotNull ByteArrayInputStream stream) {
try {
byte[] serialized = ByteStreams.toByteArray(stream);
Comparable deserialized = deserialize(serialized, Comparable.class);
return deserialized;
} catch (Exception e) {
}
return null;
}
@Override
public void writeObject(@NotNull LightOutputStream output, @NotNull Comparable object) {
byte[] serialized = serialize(object);
output.write(serialized);
}
public static byte[] serialize(Object obj) {
try {
try (ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutput out = new ObjectOutputStream(bos)) {
out.writeObject(obj);
return bos.toByteArray();
}
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
public static <T> T deserialize(byte[] data, Class<T> clazz) {
try {
ByteArrayInputStream in = new ByteArrayInputStream(data);
ObjectInputStream is = new ObjectInputStream(in);
return (T) is.readObject();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return null;
}
}
恐怕我的方法对于保存 null 值这样简单的工作来说有点矫枉过正?
registerCustomPropertyType
几次是安全的,尽管通常在初始化阶段调用一次。
如果我真的需要区分缺少 属性 值和 属性 具有空值,那么我会尝试定义非空值来替换空值。对于 String
,它可以是 UUID 的十六进制表示。对于Integer
、Integer.MIN_VALUE
或Integer.MAX_VALUE
等,不要对单个属性使用混合类型的值,否则按属性值或范围搜索不行。
由于实体存储在存储空值时抛出,我设法得到一个 "hack" 来将空值保存到其中。但是我不确定我的方法是否徒劳。
这是一个片段:
entityStore.executeInTransaction(new StoreTransactionalExecutable() {
@Override
public void execute(@NotNull final StoreTransaction txn) {
try {
entityStore.registerCustomPropertyType(txn, UndefinedIterable.class, UndefinedBinding.BINDING);
} catch (Exception e) {
}
final Entity entity = txn.newEntity(storeName);
Iterator<String> it = comparableMap.keySet().iterator();
while (it.hasNext()) {
String key = it.next();
Comparable value = comparableMap.get(key);
if(value == null) {
entity.setProperty(key, new UndefinedIterable());
} else {
entity.setProperty(key, value);
}
}
这里的第一个问题是,一遍又一遍地 registerCustomPropertyType
是否安全,因为每次服务器收到 POST 请求时都会调用此方法。
接下来这里还需要UndefinedIterable
吗?
完整代码如下
UndefinedIterable.java
public class UndefinedIterable implements Serializable, ByteIterable {
private byte[] bytes;
public UndefinedIterable() {
bytes = "null".getBytes();
}
@Override
public ByteIterator iterator() {
return new ArrayByteIterable(bytes).iterator();
}
@Override
public byte[] getBytesUnsafe() {
return bytes;
}
@Override
public int getLength() {
return bytes.length;
}
@NotNull
@Override
public ByteIterable subIterable(int offset, int length) {
return null;
}
@Override
public int compareTo(@NotNull ByteIterable o) {
return 0;
}
}
UndefinedBinding.java
public class UndefinedBinding extends ComparableBinding {
public static final UndefinedBinding BINDING = new UndefinedBinding();
@Override
public Comparable readObject(@NotNull ByteArrayInputStream stream) {
try {
byte[] serialized = ByteStreams.toByteArray(stream);
Comparable deserialized = deserialize(serialized, Comparable.class);
return deserialized;
} catch (Exception e) {
}
return null;
}
@Override
public void writeObject(@NotNull LightOutputStream output, @NotNull Comparable object) {
byte[] serialized = serialize(object);
output.write(serialized);
}
public static byte[] serialize(Object obj) {
try {
try (ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutput out = new ObjectOutputStream(bos)) {
out.writeObject(obj);
return bos.toByteArray();
}
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
public static <T> T deserialize(byte[] data, Class<T> clazz) {
try {
ByteArrayInputStream in = new ByteArrayInputStream(data);
ObjectInputStream is = new ObjectInputStream(in);
return (T) is.readObject();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return null;
}
}
恐怕我的方法对于保存 null 值这样简单的工作来说有点矫枉过正?
registerCustomPropertyType
几次是安全的,尽管通常在初始化阶段调用一次。
如果我真的需要区分缺少 属性 值和 属性 具有空值,那么我会尝试定义非空值来替换空值。对于 String
,它可以是 UUID 的十六进制表示。对于Integer
、Integer.MIN_VALUE
或Integer.MAX_VALUE
等,不要对单个属性使用混合类型的值,否则按属性值或范围搜索不行。