【发布时间】:2015-11-14 03:35:19
【问题描述】:
我有一个这样的 POJO 结构
@Entity
public class ClassA {
@Id
public Long id;
public ClassB classbObject;
}
还有一个班级
@Entity
public class ClassB {
@Id
public Long id;
public String fieldA;
public String fieldB;
}
现在,根据自定义条件,我需要将 classbObject 保存为嵌入的(Objectify 的默认行为)或仅 id 属性(这里是 Translator)。
此条件也适用于单个字段ClassA 或多个字段List<ClassA>
如果对象只保存为 ID,我还需要对其进行索引以对其进行查询。
我已经在Objectify board 上询问过,回复既有用(使用翻译器)又不完整(我找不到任何关于如何使用翻译器界面的文档)。
那么我现在面临两个问题:
1) 仅将翻译器应用于特定对象(不保存嵌入对象,仅保存 id),而不是与同一种类相关的所有对象。
使用 JPA,可以使用 @Converter 注释来发出此请求
所以,通过这种设计,类应该是这样的
@Entity
public class ClassA {
@Id
public Long id;
@MyCustomTranslator
public ClassB classbObject;
// Default behaviour
public ClassB embeddedObject;
}
我需要指定我不需要混合持久性,Java 变量将始终以相同的方式保存(嵌入或只是 id),但我需要区分一个类(例如)是否有两个变量相同的类型,或者我在 2 个不同的类中有相同的变量类型
2) 替代第一点,将决策移到 Translator 本身中,因此“将 pojo 转换为 id”代码使用编码假设来确定对象是否应存储为默认嵌入或将其转换为 ID 值.
在没有文档的情况下,我试图从 Objectify 源代码中模拟已经存在的翻译器,但我无法获得一个可以工作的翻译器。
这是我第一次尝试
public class TestTranslator implements TranslatorFactory<ClassA, Long> {
@Override
public Translator<ClassA, Long> create(TypeKey<ClassA> arg0, CreateContext arg1, Path arg2) {
return new CustomTranslator();
}
public static class CustomTranslator implements Translator<ClassA, Long> {
@Override
public ClassA load(Long arg0, LoadContext arg1, Path arg2) throws SkipException {
ClassA a = new ClassA();
a.id = arg0;
// Other custom code
return a;
}
@Override
public Long save(ClassA arg0, boolean arg1, SaveContext arg2, Path arg3) throws SkipException {
return arg0.id;
}
}
}
这是我用于初始化的代码
ObjectifyService.factory().getTranslators().add(new TestTranslator());
ObjectifyService.register(ClassA.class);
ObjectifyService.register(ClassB.class);
这不起作用,因为我在初始化期间得到了很长的堆栈跟踪,主要错误
TestTranslator$CustomTranslator cannot be cast to com.googlecode.objectify.impl.translate.ClassTranslator
另外,这并不能解决我的第 1 个问题,所以我无法决定是正常嵌入对象还是应用我的翻译器。
第二次尝试,使用 Translator 的另一个超类
public class TestValueTranslator extends ValueTranslatorFactory<ClassA, Long> {
public TestValueTranslator() {
super(ClassA.class);
}
@Override
protected ValueTranslator<ClassA, Long> createValueTranslator(TypeKey<ClassA> tk, CreateContext ctx, Path path) {
return new ValueTranslator<ClassA, Long>(Long.class) {
@Override
protected ClassA loadValue(Long value, LoadContext ctx, Path path) throws SkipException {
ClassA a = new ClassA();
a.id = value;
// Other custom code
return a;
}
@Override
protected Long saveValue(ClassA value, boolean index, SaveContext ctx, Path path) throws SkipException {
return value.id;
}
};
}
}
和上面一样的错误
TestValueTranslator$1 cannot be cast to com.googlecode.objectify.impl.translate.ClassTranslator
Objectify 似乎在强迫我使用 ClassTranslator,我试图实现它
public class TestClassTranslatorFactory extends ClassTranslatorFactory<ClassA> {
@Override
public ClassTranslator<ClassA> create(TypeKey<ClassA> tk, CreateContext ctx, Path path) {
// ????
return super.create(tk, ctx, path);
}
public class TestClassTranslator extends ClassTranslator<ClassA> {
public TestClassTranslator(Class<ClassA> declaredClass, Path path, Creator<ClassA> creator, Populator<ClassA> populator) {
super(declaredClass, path, creator, populator);
}
@Override
public ClassA loadSafe(PropertyContainer arg0, LoadContext arg1, Path arg2) throws SkipException {
EmbeddedEntity e = (EmbeddedEntity) arg0;
Long id = (Long) e.getProperty("id");
ClassA a = new ClassA();
a.id = id;
// Other custom code
return a;
}
@Override
public PropertyContainer saveSafe(ClassA arg0, boolean arg1, SaveContext arg2, Path arg3) throws SkipException {
EmbeddedEntity e = new EmbeddedEntity();
e.setProperty("id", arg0.id);
return e;
}
}
}
这里有两个问题:
1) 我不明白如何在TestClassTranslatorFactory 构造函数中创建TestClassTranslator 对象。
2)即使这个类有效,我也不得不创建一个嵌入式实体(里面有id),我不能保存为纯长(o List)。因此,我不确定是否可以完成索引部分。
最后,2个问题:
1) 是否有正确的Translator 将类对象转换为纯ID?
2) 转换器如何只应用于某些相同类型的变量?
【问题讨论】:
标签: java google-app-engine entity objectify pojo