Странное поведение JPA, инициализированное поле является пустым

Я наблюдаю очень странное поведение с классом объекта и загружаюсь, объект этого класса с JPA (будьте в спящем режиме entitymanager 3.3.1.ga). Класс имеет (встроенное) поле, которое инициализируется в объявлении. Метод set поля реализует пустую проверку (т.е. выдал бы исключение, когда нулевое значение установлено).

...
@Entity
public class Participant extends BaseEntity implements Comparable<Participant> {
   ...
    @Embedded
 private AmsData amsData = new AmsData();

 public void setAmsData(AmsData amsData) {
  Checks.verifyArgNotNull(amsData, "amsdata");
  this.amsData = amsData;
 }
    ...
}

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

...
public class ParticipantJpaDao implements ParticipantDao {
 @PersistenceContext
 private EntityManager em;

 @Override
 public Participant getParticipant(Long id) {
  return em.find(Participant.class, id);
 }
    ...
}

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

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

17
задан Dominik 16 January 2010 в 09:07
поделиться

3 ответа

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

Причина, по которой ваш улавчик никогда не вызывается, является потому, что Hibernate доступа к вашему полю через отражение, минуя, которое вы реализовали. Это делает это, потому что вы используете полевой доступ, а не доступ на основе свойства.

Ответ Чада обеспечит функциональность, которую вы ищете, но есть предостережение (см. Ниже).

«... постоянное состояние лица доступа к сохранению Время выполнения провайдера [1] Аксессуары в стиле JavaBeans или через переменные экземпляра. Один Тип доступа (поле поле или свойство) относится к иерархии сущности. Когда Аннотации используются, размещение аннотации сопоставления на постоянные поля или постоянные Свойства класса сущности Указывает тип доступа как или доступ на поле или свойство Соответственно ... "[EJB3 настойчивость SPEC]

Итак, настолько, перемещая аннотации до установки, вы говорите JPA, что вы хотите использовать доступ на основе свойств вместо доступа на основе полей. Однако вы должны знать, этот полевой доступ - как вы в настоящее время его реализуете, - это предпочтительно для доступа на основе недвижимости. Существует пару причин, по которым базирующийся на основе недвижимости отсутствует, но один из них является то, что они вынуждены добавлять GetTers и Setters для всех ваших постоянных полей сущности, но вы не хотите, чтобы эти те же поля были восприимчивы к мутации внешними клиентами. Другими словами, используя доступ на основе недвижимости JPA, вы можете ослабить инкапсуляцию вашего объекта.

17
ответ дан 30 November 2019 в 13:34
поделиться

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

@Override
public Participant getParticipant(Long id) {
    Participant participant = em.find(Participant.class, id);
    if(participant != null && participant.getAmsData() == null)
    {
        participant.setAmsData(new AmsData());
    }
    return participant;
}

Все еще чувствует себя странно для меня ...

3
ответ дан 30 November 2019 в 13:34
поделиться

Ну, возможно, ваш объект может быть построен в два раза за кулисами. Реализации JPA обычно определяют эти поля напрямую.

Я думаю, что вам нужно поставить аннотации на геттерс и сами рассеять, если вы хотите, чтобы они были использованы. Смотрите этот ответ:

Пустые конструкторы и сортировки на jpa alteTites

1
ответ дан 30 November 2019 в 13:34
поделиться
Другие вопросы по тегам:

Похожие вопросы: