2009-06-22 4 views
11

Мне не нравится требование иметь хотя бы один пустой конструктор и публичные сеттеры на объектах JPA. Хотя я понимаю проблему на стороне EntityManager, это делает недействительными инварианты класса.Пустые конструкторы и сеттеры на JPA Entites

У кого-нибудь есть решение для этого (шаблон дизайна или уровень идиомы)?

Спасибо!

Игорь

ответ

1

С DataNucleus вы не должны добавить конструктор по умолчанию, если вы не хотите; он будет автоматически добавлен путем улучшения байт-кода. Кроме того, вы можете сохранять поля вместо свойств, следовательно, нет необходимости в публичных сеттерах.

--Andy (DataNucleus)

0

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

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

+0

также может быть защищен, а не публично –

17

С JPA требуется конструктор по умолчанию, однако вам не требуется использовать сеттеры. Вы можете выбрать стратегию доступа к свойствам (поле или метод) в зависимости от места размещения аннотаций.

Следующий код будет использовать прямой доступ к полям и будет работать как часть объекта без сеттера:

@Column(name = DESCRIPTION) 
private String description; 

public String getDescription() { return description; } 

Versus метод доступа с установщиком:

private String description; 

@Column(name = DESCRIPTION) 
public void setDescription(String description) { 
    this.description = description; 
} 

public String getDescription() { return description; } 
2

Просто сделать свой конструктор защищенный или закрытый, поэтому вы сохраняете инварианты класса!

 
public class Person { 
private String firstName; 
private String lastName; 

public Person(String firstName, String lastName) { 
    setFirstName(firstName); 
    setLastName(lastName); 
} 

// private no-arg constructor for hibernate. 
private Person() { 

} 

public String getFirstName() { 
    return firstName; 
} 
public String getLastName() { 
    return lastName; 
} 

// private setters for hibernate 
private void setFirstName(String nme) { 
    firstName = nme; 
} 
private void setLastName(String nme) { 
    lastName = nme; 
} 
} 

см. http://www.javalobby.org/java/forums/m91937279.html для деталей.

3

OpenJPA может добавить no-arg ctor как часть улучшения ваших объектов.

Именно поэтому мы четко сформулировали требование, указанное в спецификации JPA. В предыдущем ответе говорится, что вы можете сделать no-arg ctor private, но это не соответствует спецификации (я вижу, что ссылка указывает на конкретную страницу Hibernate). Spec указывает, что Entity должен иметь общедоступный или защищенный no-arg ctor.

-Rick

6

В самом деле, вы должны иметь как не-арг конструктор и методы получения и установки. Требования указаны в разделе 2.1 раздела spec.

Требование конструктора без аргументов можно найти на странице 17, в моем экземпляре:

класса

Предприятия должен иметь не-Arg конструктора. Класс объекта может также иметь других конструкторов. Конструктор no-arg должен быть открыт или защищен.

страница 18 имеет требование методов доступа:

Постоянное состояние субъекта является представлен переменными экземпляра, , которые могут соответствовать ява Фасоль свойства. Переменная экземпляра может иметь вид только с использованием метода объекта с помощью объекта-объекта . У экземпляра переменные не должны быть доступны клиентам объекта. Состояние . Объект доступен для клиентов только через аксессуар объекта методов (методы getter/setter) или другие бизнес-методы. Экземпляры переменные должны быть частными, защищенными, или видимостью пакета.

Поле против доступа к собственности указывает, как поставщик JPA взаимодействует с вашей сущностью, а не как клиентское приложение взаимодействует с ним. Клиент должен всегда использовать методы get и set.

Некоторые поставщики JPA более мягкие в этих требованиях, и вы можете сделать конструктор закрытым (как было предложено выше) с конкретным поставщиком. Приложение может быть не переносимым, так что вы можете оказаться в неожиданности, если будете мигрировать в будущем.

Поэтому я бы не рекомендовал полностью исключать методы. Чтобы решить проблему, я бы назвал публикацию no-arg ctor устаревшей (добавьте что-то в javadoc о том, что она используется только для провайдера JPA). Методы набора могут содержать логику, которую вы хотите сохранить ваши инварианты.

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

+2

Во второй цитате вы заявляете, что другие классы в приложении пользователя не должны напрямую обращаться к полям объекта. Он не требует, чтобы аксессоры существовали для провайдера JPA. Фактически, самое следующее предложение: «Постоянное состояние объекта получает доступ к исполняемому файлу службы сохранения продолжительности либо через JavaBeans атрибуты свойств стиля (« доступ к свойствам »), либо через переменные экземпляра (« доступ к полю »)». Мне кажется совершенно очевидным, что вам не нужны аксессоры, если вы используете доступ к полю, что позволяет вам иметь переменные только для чтения. – Pace

Смежные вопросы