Я наблюдаю очень странное поведение с классом объекта и загружаюсь, объект этого класса с 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);
}
...
}
Я отладил процесс с контрольной точкой на поле (должен остановиться, когда к полю получают доступ или изменяют), и я вижу одну модификацию, когда поле инициализируется, но когда я получаю результат вызова находки, поле является пустым.
Кто-либо может объяснить, почему это так? Как я могу удостовериться, что поле не является пустым, также когда нет никаких данных для полей внедренного объекта в дб (кроме того, от установки его вручную после вызова находки).
Спецификация JPA не говорит о том, как обрабатывать набор столбцов, представляющих встроенный объект, который все пусто. Это может сигналировать нулевую ссылку или экземпляр объекта со всеми нулевыми полями. Hibernate выбирает нулевую ссылку в этом случае, хотя другие реализации JPA могут выбрать позже.
Причина, по которой ваш улавчик никогда не вызывается, является потому, что Hibernate доступа к вашему полю через отражение, минуя, которое вы реализовали. Это делает это, потому что вы используете полевой доступ, а не доступ на основе свойства.
Ответ Чада обеспечит функциональность, которую вы ищете, но есть предостережение (см. Ниже).
«... постоянное состояние лица доступа к сохранению Время выполнения провайдера [1] Аксессуары в стиле JavaBeans или через переменные экземпляра. Один Тип доступа (поле поле или свойство) относится к иерархии сущности. Когда Аннотации используются, размещение аннотации сопоставления на постоянные поля или постоянные Свойства класса сущности Указывает тип доступа как или доступ на поле или свойство Соответственно ... "[EJB3 настойчивость SPEC]
Итак, настолько, перемещая аннотации до установки, вы говорите JPA, что вы хотите использовать доступ на основе свойств вместо доступа на основе полей. Однако вы должны знать, этот полевой доступ - как вы в настоящее время его реализуете, - это предпочтительно для доступа на основе недвижимости. Существует пару причин, по которым базирующийся на основе недвижимости отсутствует, но один из них является то, что они вынуждены добавлять GetTers и Setters для всех ваших постоянных полей сущности, но вы не хотите, чтобы эти те же поля были восприимчивы к мутации внешними клиентами. Другими словами, используя доступ на основе недвижимости JPA, вы можете ослабить инкапсуляцию вашего объекта.
Ответ (благодаря 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;
}
Все еще чувствует себя странно для меня ...
Ну, возможно, ваш объект может быть построен в два раза за кулисами. Реализации JPA обычно определяют эти поля напрямую.
Я думаю, что вам нужно поставить аннотации на геттерс и сами рассеять, если вы хотите, чтобы они были использованы. Смотрите этот ответ: