Использование встроенного вложенного класса для представления сложного состояния в JPA

#java #jpa #eclipselink

#java #jpa #eclipselink

Вопрос:

Я пытаюсь использовать внутренний класс как встраиваемый для представления некоторых сложных свойств внешнего класса. Когда я сохраняю это, в схеме базы данных, сгенерированной eclipselink, нет информации из внутреннего класса.

Кажется ли хорошей идеей то, что я пытаюсь сделать? Почему eclipselink, похоже, не распознает их @Basic атрибут в getRate() в Attributes ?

Некоторая другая информация: Measure должен быть создан экземпляр с использованием фабрики, которая предоставляется конструктору Person , поэтому я даже не знаю, как я вообще смогу это использовать. Кажется все более вероятным, что мне придется создать отдельный класс просто для хранения состояния Person в простых терминах (например, doubles, не Measures ) и использовать их для создания объектов реального Person типа, но это имеет очень печальные последствия для остальной части моего приложения.

   @Entity
  public static class Person {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private int id;
    @Transient
    public Measure<Double, CleanupRate> rate;
    @Embedded
    private Attributes attributes;

    @Embeddable
    public static class Attributes {

      @Transient
      private Person person;

      public Attributes() {

      }

      public Attributes(Person person) {
        this.person = person;
      }

      @Basic
      public double getRate() {
        return person.rate.getInternalValue();
      }

      public void setRate(double value) {
        person.rate.setInternalValue(value);
      }
    }

    public Person() {
      rate = udm.getMeasureFactory().createMeasure(0.0, CleanupRate.class);
      attributes = new Attributes(this);
    }

    public void setRate(double rate) {
      this.rate.setValue(rate);
    }
  }
  

Редактировать:

Чтобы внедрить зависимость меры в мои объекты, когда они извлекаются из хранилища, я добавил интерфейс, который внедряет зависимость, и использовал его в моем DAO. Поскольку DAO может быть внедрен, я могу распространить зависимость вплоть до извлекаемых объектов. Я почерпнул идею из блога.

   private <T extends UomInjectable> List<T> //
          getListOfUomInjectableType(final Class<T> klass) {
    List<T> result = getListOfType(klass);
    for (UomInjectable injectable : result) {
      injectable.injectUomFactory(udm);
    }
    return resu<
  }
  

Ответ №1:

Он использует тип доступа из класса Person, для которого задано значение field , и поэтому не видит аннотацию на уровне свойств.

Вам нужно будет изменить тип доступа, используя Access (СВОЙСТВО) для встраиваемого класса, и следует удалить аннотацию @Transient в атрибуте person.

Ответ №2:

Я думаю, что в целом у вас возникнут проблемы с объектами (встраиваемыми или иными), которым нужны конструкторы с аргументами. Я не уверен, как это может быть связано с вашей проблемой генерации схемы, но я думаю, что это будет проблемой при попытке сохранить / извлечь эти объекты.

Как вы намекнули, JPA требует, чтобы все типы сущностей имели конструктор без аргументов. Хотя в вашем классе атрибутов есть один, он оставляет поле ‘person’ равным null, что довольно быстро приведет к NPE. То же самое с конструктором Person (возможно, вы пропустили тот, который передается в ‘udm’ из примера кода?).

Комментарии:

1. Да, это просто тестовый код внутри модульного теста (вот почему Person статичен), поэтому udm определен в тестовом классе.

2. Я смог обойти наличие ссылки на Person внутренние атрибуты, используя @PostLoad метод внутри Person , который считывает значения из объекта attributes. Все еще думаю о том, как я собираюсь создавать экземпляры Measure объектов, не прибегая к Singleton.

Ответ №3:

Чтобы задать Person для атрибутов, просто используйте property access лично и задайте его в вашем методе SetAttributes.

Смотрите, http://en.wikibooks.org/wiki/Java_Persistence/Embeddables#Relationships