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

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

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

Hibernate и код в целом, который создает объекты через reflection, использует Class.newInstance() для создания нового экземпляра ваших classов. Этот метод требует, чтобы публичный конструктор no-arg мог создавать экземпляр объекта. Для большинства случаев использование конструктора no-arg не является проблемой.

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

Спящий режим запускает объекты. Таким образом, он должен иметь возможность создавать их. Если конструктор no-arg отсутствует, Hibernate не будет знать, как его создать, то есть, какой аргумент должен пройти.

В документации спящего режима говорится:

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

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

Спящий режим представляет собой структуру ORM, которая поддерживает страtagsю доступа к полям или свойствам. Однако он не поддерживает построение на основе конструктора – возможно, что бы вы хотели? – из-за некоторых

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

 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, ); 

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

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

 Person person = (Person) session.get(Person.class, ); 

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

 Person.class.newInstance(); 

Что по документации API

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

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

 Person.class.newInstance(); 

похож на

 new Person(); 

Ничего больше

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

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

Но Hibernate не требует такого.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

http://kristian-domagala.blogspot.com/2008/10/proxy-instantiation-problem-from.html

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

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

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

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

  • Должен ли я преобразовывать объекты Entity (Persistent) в объекты DTO?
  • Bypass GeneratedValue в спящем режиме (данные объединить не в db?)
  • ORM для DELPHI win32
  • Hibernate, iBatis, Java EE или другой инструмент Java ORM
  • Когда и почему сущности JPA должны реализовывать интерфейс Serializable?
  • Примитив или shell для первичных ключей спящего режима
  • Родные запросы JPA / Hibernate не распознают параметры
  • Какова лучшая страtagsя для модульных приложений, управляемых базами данных?
  • Любые хорошие инструменты ORM для разработки Android?
  • Как обновить схемы таблиц базы данных с помощью генерации схемы NHibernate?
  • Какова проблема с запросом SELECT N + 1?
  • Давайте будем гением компьютера.