ColdFusion ORM и конструкторы по умолчанию (метод инициализации)

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

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

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

Единственный обходной путь, который я нашел, - это объявить другой пользовательский метод, который я использую в качестве конструктора, который делает экземпляры объектов теперь похожими на new SomeEntity().construct(...) или createObject('component', 'SomeEntity').construct(...). Это довольно хлопотно...

Что очень глупо во всем этом, так это то, что вы можете создать экземпляр сущности, не вызывая метод init, используя createObject, поэтому мне интересно, почему они решили заставить Hibernate вызывать метод init в своей реализации, учитывая тот факт, что он даже не передает параметры, а устанавливает их потом другими средствами.

В любом случае, есть ли другие способы решения этой проблемы?

РЕДАКТИРОВАТЬ:

Я зарегистрировал ошибку в базе ошибок Adobe.


person plalx    schedule 01.02.2015    source источник
comment
Поскольку ORM, похоже, не может обрабатывать «всегда действительные объекты», он «совершенно бесполезен»? Пожалуйста, объясни.   -  person Scott Stroz    schedule 02.02.2015
comment
@ScottStroz Что ж, если вы похожи на меня и считаете, что сущности всегда должны быть действительными, вы не позволите создавать экземпляры своих классов без применения инвариантов. Например. если в моем домене концепция Person должна иметь name, то я бы не позволил создавать экземпляр компонента Person без него, но это не позволит мне использовать CF-ORM, потому что функция init будет вызываться без аргументов при регидратации объектов. Это не проблема в языках, где конструктор может быть перегружен.   -  person plalx    schedule 02.02.2015
comment
Я не уверен, что вы подразумеваете под «регидратацией» объектов. Вы говорите о том, что при сохранении объекта вам нужно передать аргументы, которые будут передавать свойства для этого объекта? Если это так, вы можете просто использовать что-то вроде new Person( {firstName: 'Bob', lastName: 'Johnson'}). Хотя, я считаю, что это было введено в CF10. Всегда можно было обновить.   -  person Scott Stroz    schedule 02.02.2015
comment
@ScottStroz Регидратация происходит, когда спящий режим загружает данные из базы данных и использует отражение для установки значений компонентов. С CF-ORM Hibernate будет вызывать конструктор компонента, как если бы это был конструктор без аргументов, и, следовательно, произойдет сбой. Не могли бы вы попробовать это в CF10 и посмотреть, что это даст? Убедитесь, что ваши аргументы конструктора являются обязательными.   -  person plalx    schedule 02.02.2015
comment
ОК ... так что я не так понял «регидратация», спасибо за разъяснение, хотя это привело к другой путанице. Почему/как вы используете createObject() или new Person() для загрузки данных из базы данных? Я не уверен, что это лучший способ извлечения данных объекта из базы данных в ColdFusion. Я склонен использовать entityLoad() при загрузке нескольких объектов - или с использованием нескольких критериев или entityLoadByPK(), когда у меня есть ПК для определенного объекта. Единственный раз, когда я буду использовать createObject() или new Person(), это когда я создаю новый экземпляр.   -  person Scott Stroz    schedule 02.02.2015
comment
Я был бы рад протестировать что-нибудь в ColdFusion 10, если бы у вас был пример кода, который я мог бы попробовать.   -  person Scott Stroz    schedule 02.02.2015
comment
@ScottStroz Вы меня неправильно понимаете. Это то, что я говорю. Когда вы вызываете entityLoad, Hibernate регидратирует ваши сущности. Для этого он сначала вызовет конструктор для создания новых экземпляров компонента, а затем будет использовать отражение для установки полей.   -  person plalx    schedule 02.02.2015
comment
Я это понимаю. Чего я не понимаю, так это почему это делает его «совершенно бесполезным»? Я также не понимаю, как использование createObject().constructor() или new Person().constructor() позволяет загружать данные из базы данных и заполнять свойства.   -  person Scott Stroz    schedule 02.02.2015


Ответы (3)


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

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

person Henry    schedule 01.02.2015
comment
Что ж, всегда действительные сущности являются де-факто в Domain-Driven Design (DDD). Я не хочу начинать борьбу между разными школами мысли, но ИМХО сущности, которым разрешено быть недействительными, могут быть в порядке в простом домене CRUD с ActiveRecord, но им нет места в DDD. Кроме того, я не понимаю, как наличие дополнительной сопоставленной абстракции поможет регидратации доменных объектов? Вам все равно нужно будет сопоставить новые сущности, ориентированные на постоянство, с объектами предметной области. Спящий режим здесь вообще не проблема, проблема связана с плохой реализацией ColdFusion, и это очень расстраивает. - person plalx; 02.02.2015

Если бы у сущности не было пустого конструктора, то Hibernate не знал бы, какие параметры предоставлять при создании экземпляра сущности.

Вы можете сделать конструктор по умолчанию protected, и Hibernate найдет его, потому что PojoInstantiator использует объявленный конструктор:

constructor = ReflectHelper.getDefaultConstructor( mappedClass );

Вы можете определить Builder для создания объектов вместо использования перегруженных конструкторов.

Таким образом, вы можете установить, что только Builder используется вашим клиентским API, а не конструктором по умолчанию.

person Vlad Mihalcea    schedule 14.03.2015
comment
Что ж, если мне нужно использовать конструктор, я предпочту использовать подход new Object().constructor(). Использование построителя для каждого класса было бы неправильным использованием шаблона. Еще раз, еще одно мнение, которое делает ColdFusion таким плохим корпоративным языком... - person plalx; 24.03.2015

После многих усилий по утверждению этого запроса проблема была исправлена.

Нимит Шарма

5:08:05 GMT+00:00 20 ноября 2015 г.

Эта проблема устранена, и исправление будет доступно в следующем основном выпуске ColdFusion.

Для решения этой проблемы мы ввели свойство orminitmethod на уровне компонентов. Подкомпонент не наследует метод minit. Он ведет себя точно так же, как initmethod.

Я зарегистрировал еще одну ошибку отслеживания # 4090267, чтобы иметь настройку на уровне приложения.

person plalx    schedule 16.09.2016