Постоянный провайдер для Java, который поддерживает финальные поля - PullRequest
7 голосов
/ 16 марта 2010

Я очень новичок в Java, но у меня выработалась привычка использовать final везде, где это возможно, объявляя неизменность, что я считаю хорошей вещью. (Рассмотрим f #)

Я читал, что JPA не поддерживает конечные поля. Спящий, TopLink? Я не уверен в этом, но сейчас я предпочитаю JPA.

Возможно ли даже теоретически - скажем, посредством размышления - изменить конечные поля после создания? Мое предположение было бы ... НЕТ:)

Что, безусловно, возможно для персистентного решения, - это поддержка конструкторов с параметрами. По крайней мере, я не вижу причин, которые сделали бы это невозможным. Думаю, картографирование будет немного сложным. Это альтернативное решение.

Предложения

РЕДАКТИРОВАТЬ: Я не знаком с точным определением неизменяемого, поэтому я использовал его в этом посте интуитивно. Объявление неизменности здесь означает объявление того, что поле не может быть изменено. Извините за недоразумение.

Ответы [ 5 ]

6 голосов
/ 16 марта 2010

Неизменность объекта (обратите внимание на разницу между неизменяемым объектом и объявлением поля final - объект ТОЛЬКО неизменен, если ВСЕ поля являются окончательными, поэтому состояние объекта не может измениться после создания) - очень деликатная тема. Они мне нравятся, и Hibernate поддерживает их через @ Immutable.

Не знаю о его состоянии в JPA 2, но чтобы ответить на вопрос о последних полях: вы МОЖЕТЕ изменить их значения с помощью отражения - но отражение в среде Java EE строго ограничено.

Чтобы прояснить основную проблему: если ваши POJO неизменны, то как постоянное решение может воссоздать объекты? Допустим, у вас есть два последних поля типа int и конструктор для их инициализации. Уровень персистентности не может иметь никакой информации об их порядке или их именах (поскольку имена полей и параметров стираются во время компиляции).

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

3 голосов
/ 16 марта 2010

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

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

1 голос
/ 22 октября 2014

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

Спецификация JPA ясна в отношении полей:

Класс сущности не должен быть окончательным. Никакие методы или постоянные переменные экземпляра класса сущности не могут быть окончательными.

Однако не все реализации следуют этому правилу и обрабатывают конечные поля:

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

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

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

0 голосов
/ 16 марта 2010

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

Как правило, персистентные структуры имеют дело с иерархиями "нормальных" объектов. У вас есть объекты, которые можно только создавать и удалять, но не изменять. Это очень странно, потому что когда вы создаете сущность, вы создаете для нее какой-то идентификатор. Через этот идентификатор вы связываете сущность с другими. Когда вы удаляете старую сущность и создаете другую, вы (в общем) получаете сущность с другим идентификатором. Итак, все соединения (внешние ключи) разорваны. Это целевое поведение?

0 голосов
/ 16 марта 2010

Это, честно говоря, странная идея.

Делая поля final, вы сообщаете компилятору, что они никогда не изменятся после создания объекта. Как следствие, это разумное предположение не сохранять их, так как они никогда не изменятся. Что ж, написав это, я предполагаю, что у вас есть культура Java, но вопрос, который вы задаете, точно говорит об обратном.

В Java постоянные объекты «всегда» предполагаются как POJO (другими словами, Java Beans). Бин Java должен иметь (чтобы считаться таковым) пустой конструктор, который позволит структурам персистентности и т. Д. Конструировать его, используя его пустой конструктор, косвенно вызывая его через Class.newInstance () /.

Существуют поля, в которых используются непустые конструкторы (например, контейнеры IoC - Guice, Spring и Tapestry IoC), но это выходит за рамки Java Beans, которые должны рассматриваться как объекты данных.

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