2015-08-20 3 views
0

У меня есть POJO структуру, подобную этойобъективизации Переводчик в JPA Attribute конвертер

@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, и ответ полезен (используйте Переводчик) и неполный (я не могу найти документацию о том, как использовать интерфейс Translator).

Две проблемы, то я столкнулся в настоящее время:

1) Нанести переводчик только к конкретным объектам (не сохраняя внедренный объект, но только идентификатор) и не все объекты, связанные с такого же рода.

С JPA этот запрос может быть сделан с использованием @Converter аннотацию Итак, с этим проектом, класс должен быть чем-то вроде этого

@Entity 
public class ClassA { 

    @Id 
    public Long id; 

    @MyCustomTranslator 
    public ClassB classbObject; 

    // Default behaviour 
    public ClassB embeddedObject; 
} 

мне нужно указать, что я не нужен гибридная настойчивость, переменная Java всегда будет сохраняться одинаково (встроенный или просто id), но мне нужно дифференцировать, если класс (например) имеет две переменные того же типа или у меня один и тот же тип переменной в 2 разных классы

2) В качестве альтернативы первого пункта, переместите решение в Translator it self, поэтому код «convert pojo to id» использует кодированные предположения, чтобы определить, должен ли объект быть сохранен по умолчанию или преобразовать его в значение ID.

Без документации я попытался подражать уже существующему Translator из исходного кода 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); 

Это не работает, потому что я очень долго StackTrace во время init, с основной погрешностью

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

Кроме того, это не решение моей проблемы номер 1, поэтому я не могу решить, вставлять объект как обычно или применять мой переводчик.


Вторая попытка, с другой суперкласс Переводчик

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 

Кажется, что объективизировать заставляет меня использовать 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) Даже если этот класс работает, я могу создать встроенный объект (с идентификатором внутри), и я не могу сохранить его как чистый Long (o List). Из-за этого часть индексации, которую я не уверен, может быть выполнена.

В конце, 2 вопроса: 1) Есть ли правильный Translator для преобразования объекта класса в чистый id? 2) Как конвертер может применяться только к определенным переменным того же типа?

ответ

1

Здесь многое происходит, и stackoverflow, вероятно, является плохим форматом для диалога назад и вперед, который в конечном итоге приведет вас туда, где вы хотите быть. Существует google group, который, вероятно, будет более полезен.

Ваша первая проблема заключается в том, что для договора TranslatorFactory требуется, чтобы create() был возвращен null, если TypeKey не подходит для этой фабрики. Во время регистрации фабрики проверяются, пока один из них не преуспеет; Translator затем становится частью быстрой, но статической метамодели для перевода между POJO и Entities. Всегда возвращая переводчика, вы «требуете» все в течение этого периода открытия. Поэтому проверьте правильность типа и верните null, если тип не для вас.

Еще одна полезная информация состоит в том, что есть аннотация, которую вы можете использовать в определенных полях, которые заставят их обрабатывать конкретный переводчик. Вы можете использовать это с заводами, которые вы не регистрируете заранее, поэтому вы можете выборочно изменять поведение определенных полей, не затрагивая другие виды использования этого типа.

0

Решено использовать @Translate, который может быть применен к определенным полям