2010-03-16 6 views
5

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

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

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

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

Предложения?

EDIT: Я не знаком с точным определением неизменяемости, поэтому я использовал его в этом посте интуитивно. Объявление Immutability здесь означает объявление о том, что поле не может быть изменено. Извините за недопонимание.

ответ

6

Неизбежность объекта (обратите внимание на разницу между неизменяемым объектом и объявлением конечного поля - объект ТОЛЬКО НЕОБХОДИМО, если все поля являются окончательными, поэтому состояние объекта не может измениться после создания) является очень чувствительной темой. Я люблю их сам, а спящий режим поддерживает их через @Immutable.

Не знаю об этом статусе в JPA 2, но чтобы ответить на вопрос о конечных полях: вы можете изменить их значения с помощью отражения, но отражение в среде Java EE сильно ограничено.

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

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

-1

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

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

В Java постоянные obejcts всегда считаются POJO (другими словами, Java Beans). Java Bean должен иметь (чтобы считаться таковым) пустой конструктор, который позволит структурам persistance и т. Д. Построить его с помощью своего пустого конструктора, косвенно называя его через Class.newInstance() /.

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

+0

Как насчет базы данных только для чтения? Кстати, я просто изучаю возможности. – naeron84

+0

Другие варианты использования: несколько объектов для одной таблицы. Или создавать эти объекты с помощью заводского метода. – naeron84

1

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

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

0

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

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

+0

Вы делаете несколько действительных баллов; +1. –

1

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

JPA Spec ясно относительно конечных полей:

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

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

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

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

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

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