Почему Hibernate не требует конструктора аргументов?

  

Конструктор без аргументов   требование (такие инструменты, как использование Hibernate   отражение на этом конструкторе   создавать объекты).

Я получил этот волнообразный ответ, но кто-нибудь может объяснить дальше? Благодаря

77 голосов | спросил unj2 29 Maypm10 2010, 20:43:58

9 ответов


0

Hibernate и код в целом, который создает объекты с помощью отражения, используют Class<T>.newInstance() , чтобы создать новый экземпляр ваших классов. Этот метод требует, чтобы общедоступный конструктор без аргументов мог создать экземпляр объекта. В большинстве случаев использование конструктора без аргументов не является проблемой.

Существуют хаки, основанные на сериализации, которые могут обходиться без использования конструктора без аргументов, поскольку сериализация использует магию jvm для создания объектов без вызова конструктора. Но это доступно не для всех виртуальных машин. Например, XStream может создавать экземпляры объектов, которые не имеют открытого конструктора без аргументов, но только при работе в так называемом «расширенном» режиме, который доступен только на определенных виртуальных машинах. (Для получения подробной информации см. Ссылку.) Дизайнеры Hibernate, безусловно, решили поддерживать совместимость со всеми виртуальными машинами, поэтому избегают таких уловок и используют официально поддерживаемый метод отражения Class<T>.newInstance() требующий конструктора без аргументов.

ответил mdma 4 J0000006Europe/Moscow 2010, 09:32:33
0

Hibernate создает ваши объекты. Так что это должно быть в состоянии создать их экземпляр. Если нет конструктора без аргументов, Hibernate не будет знать, как его создать, то есть какой аргумент передать.

документация гибернации гласит:

  

4.1.1. Реализовать конструктор без аргументов

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

ответил Bozho 29 Maypm10 2010, 20:47:15
0

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

(На самом деле, JAXB предположительно допускает фабрики сущностей, но он настаивает на том, чтобы создавать эти фабрики самостоятельно, требуя, чтобы у них был --guess what-- беспараметрический конструктор , который в моей книге точно такой же, как хорошо, что не пускает фабрики; как это неубедительно!)

Но Hibernate не требует такой вещи.

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

По сути, вы делаете, что при настройке гибернации вы передаете ему объект, реализующий интерфейс org.hibernate.Interceptor, и тогда спящий режим будет вызывая метод instantiate() этого интерфейса всякий раз, когда ему нужен новый экземпляр вашего объекта, так что ваша реализация этого метода может new ваши объекты так, как вам нравится.

Я сделал это в проекте, и это работает как шарм. В этом проекте я делаю что-то через JPA, когда это возможно, и использую функции Hibernate, такие как перехватчик, только когда у меня нет другого выбора.

Hibernate, похоже, несколько небезопасен, поскольку во время запуска он выдает информационное сообщение для каждого из моих классов сущностей, сообщая мне INFO: HHH000182: No default (no-argument) constructor for class и class must be instantiated by Interceptor, но потом я создаю их экземпляры с помощью перехватчика, и он этому рад.

Чтобы ответить на часть вопроса «почему», касающуюся инструментов , кроме Hibernate , ответ «абсолютно без уважительной причины», и это подтверждается существованием перехватчика hibernate. Существует множество инструментов, которые могли бы поддерживать некоторый похожий механизм для создания экземпляров клиентских объектов, но они этого не делают, поэтому они сами создают объекты, поэтому им требуются конструкторы без параметров. Я испытываю желание поверить, что это происходит потому, что создатели этих инструментов считают себя системными программистами-ниндзя, которые создают фреймворки, полные магии, которые будут использоваться невежественными программистами приложений, которые (как они думают) никогда не будут в своих самых смелых мечтах иметь потребность в таких продвинутых конструкциях, как ... Заводской шаблон . (Хорошо, я склонен так думать. Я не на самом деле так думаю. Я шучу.)

ответил Mike Nakis 3 PMpFri, 03 Apr 2015 16:34:08 +030034Friday 2015, 16:34:08
0

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

Что произойдет, если в вашем классе много конструкторов

public class Person {

    private String name;
    private Integer age;

    public Person(String name, Integer age) { ... }
    public Person(String name) { ... }
    public Person(Integer age) { ... }

}

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

Person person = (Person) session.get(Person.class, <IDENTIFIER>);

Какой конструктор должен вызвать Hibernate для получения объекта Person? Ты видишь?

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

Person person = (Person) session.get(Person.class, <IDENTIFIER>);

Hibernate создаст экземпляр вашего объекта Person следующим образом

Person.class.newInstance();

Который согласно документации API

  

Класс создается как бы выражением new с пустым списком аргументов

Мораль истории

Person.class.newInstance();

похож на

new Person();

Ничего другого

ответил Arthur Ronald 9 J0000006Europe/Moscow 2010, 07:25:17
0

На самом деле, вы можете создавать экземпляры классов, которые не имеют конструктора 0-args; Вы можете получить список конструкторов класса, выбрать один и вызвать его с фиктивными параметрами.

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

Построение объектов так, как это делает Hibernate (я думаю, что он вызывает конструктор 0-arg, а затем, вероятно, изменяет поля экземпляра напрямую через Reflection. Возможно, он знает, как вызывать сеттеры), немного противоречит тому, как объект должен быть построенным в Java - вызовите конструктор с соответствующими параметрами, чтобы новый объект был тем объектом, который вам нужен. Я считаю, что создание экземпляра объекта и затем его изменение - это несколько «анти-Java» (или, я бы сказал, анти-чисто теоретическая Java) - и определенно, если вы делаете это с помощью прямого манипулирования полем, он выполняет инкапсуляцию и все такое причудливое инкапсуляция .

Я думаю, что правильный способ сделать это - определить в отображении Hibernate способ создания объекта из информации в строке базы данных с использованием правильного конструктора ... но это будет более сложным - это означает, что оба Hibernate было бы еще сложнее, отображение было бы более сложным ... и все было бы более "чисто"; и я не думаю, что это имело бы преимущество перед текущим подходом (кроме того, чтобы чувствовать себя хорошо, когда делаешься «как надо»).

Сказав это, и увидев, что подход Hibernate не очень «чистый», обязательство иметь конструктор 0-arg не является строго необходимым, но я могу несколько понять требование, хотя я полагаю, что они сделали это чисто основания "правильного пути", когда они отклонились от "правильного пути" (хотя и по разумным причинам) задолго до этого.

ответил alex 9 J0000006Europe/Moscow 2010, 01:46:45
0

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

ответил Pascal Thivent 29 Maypm10 2010, 20:50:08
0

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

Многим ORM и сериализаторам требуются конструкторы без параметров, поскольку параметризованные конструкторы посредством отражения очень хрупки, а конструкторы без параметров обеспечивают как стабильность приложения, так и контроль поведения объекта для разработчика.

ответил Kaerber 10 J0000006Europe/Moscow 2010, 12:48:26
0

Hibernate использует прокси для отложенной загрузки. Если вы не определили конструктор или сделали его закрытым, некоторые вещи все еще могут работать - те, которые не зависят от механизма прокси. Например, загрузка объекта (без конструктора) напрямую с использованием API запросов.

Но если вы используете метод session.load (), вы столкнетесь с InstantiationException из библиотеки proxy generator из-за отсутствия конструктора.

Этот парень сообщил о похожей ситуации:

http: //kristian-domagala.blogspot. ком /2008/10 /прокси-конкретизации-проблемно-from.html

ответил haps10 28 +04002011-10-28T15:23:26+04:00312011bEurope/MoscowFri, 28 Oct 2011 15:23:26 +0400 2011, 15:23:26
0

Ознакомьтесь с этим разделом спецификации языка Java, который объясняет разницу между статическими и нестатическими внутренними классами: http://java.sun.com/docs/books/jls/third_edition/html/classes.html#8.1.3

Статический внутренний класс концептуально не отличается от обычного общего класса, объявленного в файле .java.

Поскольку Hibernate должен создавать экземпляр ProjectPK независимо от экземпляра Project, ProjectPK должен быть статическим внутренним классом или объявлен в своем собственном файле .java.

reference org.hibernate.InstantiationException: нет конструктора по умолчанию

ответил Amitābha 13 +04002014-10-13T06:29:08+04:00312014bEurope/MoscowMon, 13 Oct 2014 06:29:08 +0400 2014, 06:29:08

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

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132