Hibernate не позволяет встроенному объекту с полем int быть нулевым? - PullRequest
10 голосов
/ 15 мая 2010

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

@Entity
public class Thing {

    @Id
    public String id;

    public Part part;

}

где Part - это встраиваемый класс, который выглядит следующим образом

@Embeddable
public class Part {

    public String a;    

    public int b;

}

затем попытка сохранить объект Thing с нулевой частью заставляет Hibernate выдавать исключение. В частности, этот код

Thing th = new Thing();
th.id = "thing.1";
th.part = null;
session.saveOrUpdate(th);

заставляет Hibernate выдать это исключение

org.hibernate.PropertyValueException: not-null property references a null or transient value: com.ace.moab.api.jobs.Thing.part

Я предполагаю, что это происходит потому, что Part является встроенным классом, и поэтому Part.a и Part.b являются просто столбцами в таблице базы данных Thing. Поскольку Thing.part имеет значение null, Hibernate хочет установить значения столбцов Part.a и Part.b в null для строки для thing.1. Однако Part.b является целым числом, и Hibernate не допустит, чтобы целочисленные столбцы в базе данных были нулевыми. Это то, что вызывает исключение, верно?

Так что я ищу обходные пути для этой проблемы. Я заметил, что создание Part.b целочисленным вместо целого, кажется, работает, но по причинам, которые я не буду утомлять вас этим, не является хорошим вариантом для нас. Спасибо!

Ответы [ 3 ]

7 голосов
/ 15 июня 2010

Я нашел другой обходной путь и решил поделиться им. Оказывается, если вы сделаете столбец int обнуляемым, то Hibernate не выбрасывает исключение PropertyValueException.

@Column(nullable = true)
public Integer b;

Это работает для нас, потому что наше приложение с включенным режимом гибернации - единственное, что касается базы данных, и поэтому мы можем гарантировать, что b равно нулю, только когда часть равна нулю. Хотя предложение нулевой части и использование типа-оболочки Integer - отличные предложения, по многим причинам, по которым я не могу контролировать, установка столбца в nullable работает лучше всего для нас. Хотя спасибо, и я надеюсь, что это поможет кому-то еще.

3 голосов
/ 15 мая 2010

Довольно неудобно, да. Вы можете установить значение по умолчанию для поля part:

private Part part = new Part();

или даже

private Part part = Part.NULL_PART;

(см. Паттерн нулевого объекта )

Имейте в виду, что если ваш класс @Embeddable не содержит примитива (который имеет значение по умолчанию), и вы сохраняете объект со всеми null s, вся структура будет сохранена в базе данных как null, потому что в hibernate нет способа определить разницу в БД, независимо от того, есть ли у вас объект или у вас есть пустой. Чтобы обойти это, если оно возникнет, вам нужно создать фиктивное поле (лучше всего boolean).

2 голосов
/ 15 мая 2010

Вы абсолютно правы в том, что происходит. Когда объект встроенного класса имеет значение null, Hibernate представляет это, делая все его столбцы пустыми в базе данных; к сожалению, это означает, что Hibernate не может определить разницу между встраиваемым нулевым объектом и встраиваемым объектом со всеми нулевыми значениями.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...