Ebean не может сериализовать деньги
Я пытаюсь переключить свой домашний проект на Java с рукописного SQL на Ebean. Когда я запускаю проект сейчас, я получаю сообщение
Was unable to use reflection to find a constructor and appropriate getters forimmutable type interface j`avax.money.MonetaryAmount`
с последующим большим количеством ошибок, связанных с javamoney.
Я знаю, что у MonetaryAmont есть частный конструктор, и он создается с помощью открытого статического метода. Как мне сказать Ebean, как сериализовать MonetaryAmount?
2 ответа
Я отказался от Ebean и вместо этого использовал Eclipselink. По иронии судьбы, вот где я нашел ответ на свой вопрос. Таким образом, для людей, находящихся в подобной ситуации, как я был здесь, я должен был сделать следующее:
То, что я искал, называется ScalarTypeConverter. Они не очень хорошо документированы в Ebean. Тем не менее, о GavHub есть некоторый Javadoc и, по крайней мере, одна проблема.
Реализация Serializable не требуется в Ebean
Пожалуйста, прочитайте это
Ниже приведен отрывок оттуда
открытый интерфейс Сериализуемый
Сериализуемость класса обеспечивается классом, реализующим интерфейс java.io.Serializable. Классы, которые не реализуют этот интерфейс, не будут сериализованы или десериализованы. Все подтипы сериализуемого класса сами по себе сериализуемы. Интерфейс сериализации не имеет методов или полей и служит только для определения семантики сериализации.
Чтобы разрешить сериализацию подтипов несериализуемых классов, подтип может взять на себя ответственность за сохранение и восстановление состояния открытых, защищенных и (если доступно) полей супертипа. Подтип может принять на себя эту ответственность, только если расширяемый класс имеет доступный конструктор без аргументов для инициализации состояния класса. Ошибочно объявлять класс Serializable, если это не так. Ошибка будет обнаружена во время выполнения.
Во время десериализации поля несериализуемых классов будут инициализированы с использованием открытого или защищенного конструктора no-arg класса. Конструктор без аргументов должен быть доступен для подкласса, который сериализуем. Поля сериализуемых подклассов будут восстановлены из потока.
При обходе графа может встретиться объект, который не поддерживает интерфейс Serializable. В этом случае будет выдано исключение NotSerializableException, которое определит класс несериализуемого объекта.
Классы, которые требуют специальной обработки в процессе сериализации и десериализации, должны реализовывать специальные методы с такими точными сигнатурами:
private void writeObject (java.io.ObjectOutputStream out) выбрасывает IOException private void readObject(java.io.ObjectInputStream in) выбрасывает IOException, ClassNotFoundException; private void readObjectNoData() throws ObjectStreamException;
Метод writeObject отвечает за запись состояния объекта для его конкретного класса, чтобы соответствующий метод readObject мог его восстановить. Механизм по умолчанию для сохранения полей объекта может быть вызван путем вызова out.defaultWriteObject. Метод не должен заботиться о состоянии, принадлежащем его суперклассам или подклассам. Состояние сохраняется путем записи отдельных полей в ObjectOutputStream с использованием метода writeObject или с помощью методов для примитивных типов данных, поддерживаемых DataOutput.
Метод readObject отвечает за чтение из потока и восстановление полей классов. Он может вызвать in.defaultReadObject, чтобы вызвать механизм по умолчанию для восстановления нестатических и непереходных полей объекта. Метод defaultReadObject использует информацию в потоке для назначения полей объекта, сохраненного в потоке, с соответствующими именами полей в текущем объекте. Это обрабатывает случай, когда класс эволюционировал для добавления новых полей. Метод не должен заботиться о состоянии, принадлежащем его суперклассам или подклассам. Состояние сохраняется путем записи отдельных полей в ObjectOutputStream с использованием метода writeObject или с помощью методов для примитивных типов данных, поддерживаемых DataOutput.
Метод readObjectNoData отвечает за инициализацию состояния объекта для его конкретного класса в том случае, если поток сериализации не перечисляет данный класс как суперкласс десериализуемого объекта. Это может происходить в тех случаях, когда принимающая сторона использует версию десериализованного экземпляра, отличную от версии отправляющей стороны, а версия получателя расширяет классы, которые не расширяются версией отправителя. Это может также произойти, если поток сериализации был подделан; следовательно, readObjectNoData полезен для правильной инициализации десериализованных объектов, несмотря на "враждебный" или неполный исходный поток.
Сериализуемые классы, которым необходимо указать альтернативный объект, который будет использоваться при записи объекта в поток, должны реализовывать этот специальный метод с точной сигнатурой:
ANY-ACCESS-MODIFIER Объект writeReplace() создает исключение ObjectStreamException;
Этот метод writeReplace вызывается сериализацией, если метод существует, и он будет доступен из метода, определенного в классе сериализуемого объекта. Таким образом, метод может иметь частный, защищенный и частный доступ к пакету. Доступ подкласса к этому методу следует правилам доступности Java.
Классы, которым необходимо назначить замену, когда ее экземпляр читается из потока, должны реализовывать этот специальный метод с точной подписью.
ANY-ACCESS-MODIFIER Объект readResolve() создает исключение ObjectStreamException;
Этот метод readResolve следует тем же правилам вызова и правилам доступности, что и writeReplace.
Среда выполнения сериализации связывает с каждым сериализуемым классом номер версии, называемый serialVersionUID, который используется во время десериализации для проверки того, что отправитель и получатель сериализованного объекта загрузили классы для этого объекта, которые совместимы в отношении сериализации. Если получатель загрузил класс для объекта, который имеет serialVersionUID, отличный от класса соответствующего отправителя, то десериализация приведет к исключению InvalidClassException. Сериализуемый класс может объявить свой собственный serialVersionUID в явном виде, объявив поле с именем "serialVersionUID", которое должно быть статическим, конечным и типа long:
ANY-ACCESS-MODIFIER static final long serialVersionUID = 42L;
Если сериализуемый класс явно не объявляет serialVersionUID, тогда среда выполнения сериализации вычислит значение serialVersionUID по умолчанию для этого класса на основе различных аспектов класса, как описано в Спецификации сериализации объектов Java(TM). Однако настоятельно рекомендуется, чтобы все сериализуемые классы явно объявляли значения serialVersionUID, так как вычисление serialVersionUID по умолчанию очень чувствительно к деталям класса, которые могут различаться в зависимости от реализаций компилятора, и, следовательно, могут привести к неожиданным исключениям InvalidClassExceptions во время десериализации. Поэтому, чтобы гарантировать согласованное значение serialVersionUID в различных реализациях Java-компилятора, сериализуемый класс должен объявить явное значение serialVersionUID. Также настоятельно рекомендуется, чтобы в явных объявлениях serialVersionUID использовался частный модификатор, где это возможно, поскольку такие объявления применяются только к немедленно объявленному классу - поля serialVersionUID не используются в качестве унаследованных членов. Классы массива не могут объявлять явный serialVersionUID, поэтому у них всегда есть вычисленное значение по умолчанию, но требование соответствия значений serialVersionUID отменяется для классов массива.