客观化翻译为JPA属性转换器

时间:2015-08-20 13:09:50

标签: java google-app-engine entity objectify pojo

我有像这样的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)除了第一点之外,在译者本身中移动决定,所以&#34;将pojo转换为id&#34;代码使用编码假设来确定对象是否应存储为默认嵌入或将其转换为ID值。

没有文档我试图从Objectify源代码中模拟已经存在的Translator,但是我无法使用它。

这是我尝试的第一次尝试

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;
        }
    }
}

以下是我用于init的代码

ObjectifyService.factory().getTranslators().add(new TestTranslator());

ObjectifyService.register(ClassA.class);
ObjectifyService.register(ClassB.class);

这不起作用,因为我在init期间得到一个非常长的堆栈跟踪,主错误

TestTranslator$CustomTranslator cannot be cast to com.googlecode.objectify.impl.translate.ClassTranslator

另外,这不是解决我的第一个问题,所以我无法决定是否将对象嵌入正常或应用我的翻译。

第二次尝试,与另一个超级类翻译

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)我无法理解如何在TestClassTranslator构造函数中创建TestClassTranslatorFactory对象。 2)即使这个类有效,我强制创建一个嵌入的实体(内部有id),我不能保存为纯Long(o List)。因此,索引部分I不确定是否可以完成。

最后,有两个问题: 1)是否有正确的Translator将类对象转换为纯id? 2)转换器如何仅应用于相同类型的某些变量?

2 个答案:

答案 0 :(得分:1)

这里有很多内容,stackoverflow可能是来回对话的一种糟糕的格式,最终会让你到达你想去的地方。有google group可能会更有用。

您的第一个问题是TranslatorFactory的合同要求create()如果TypeKey不适合该工厂,则返回null。在注册时,工厂按顺序进行试验,直到其中一个成功; Translator然后成为快速但静态的元模型的一部分,用于在POJO和实体之间进行转换。通过总是返回翻译,你在这个发现期间“声称”一切。因此,检查类型是否正确,如果类型不适合您,则返回null。

另一个有用的知识是有一个@Translate注释可以在特定字段上使用,这将强制它们由特定的翻译器处理。您可以将此项用于未事先注册的工厂,这样您就可以有选择地修改某些字段的行为,而不会影响该类型的其他用途。

答案 1 :(得分:0)

使用可应用于特定字段的@Translate解决