JAXB и разные версии класса - PullRequest
5 голосов
/ 28 марта 2012

Интересно, есть ли какая-либо поддержка различных версий класса в JAXB. Мои мысли по этому поводу: xml - это своего рода объект персистентности класса (сериализованное значение), но объект класса может быть изменен в результате разработки (например, расширение функциональности). Есть ли способ узнать, какая версия класса хранится в постоянстве (читай: xml), используя только JAXB API?

Для меня кажется удобным хранить версию класса - как это сделано в стандартном механизме сериализации Java (я имею в виду serialVersionUID) и обеспечивать функциональность для сопоставления XML с классом даже в случае другой версии (например, добавление в XmlAdapter информации о версии класса хранится в XML). По умолчанию, если версия класса в xml и во время выполнения отличается - сгенерировать исключение InvalidClassException.

Пример: У нас есть класс Test следующим образом:

@XmlRootElement
@XmlAccessorType(value = XmlAccessType.FIELD)
public class Test {

    private Long time;

    private Test () {}; 
}

при условии, что это время UNIX в миллисах.

Этот код был выпущен на производстве, и этот класс был сохранен в базе данных как XML. В следующем выпуске показано, что использование представления Long как времени было неправильным, и оно было изменено на Date:

@XmlRootElement
@XmlAccessorType(value = XmlAccessType.FIELD)
public class Test {

    private Date time;

    private Test () {}; 
}

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

Если мы выберем второй способ, было бы замечательно, если бы JAXB API предоставил версию класса, которая была сохранена в xml (при условии, что в классе = 0 версия класса не указана), и мы добавили новую версию класса явно (либо с помощью аннотации) или по статическому полю):

@XmlRootElement
@XmlAccessorType(value = XmlAccessType.FIELD)
@XmlClassVersion(value = 1)
public class Test {

    private Date time;

    private Test () {}; 
}

или

@XmlRootElement
@XmlAccessorType(value = XmlAccessType.FIELD)
public class Test {

    private static final long xmlSerialVersionUID = 1;

    private Date time;

    private Test () {}; 
}

и JAXB предоставит XmlAdapter следующим образом:

public abstract class XmlAdapter<ValueType,BoundType> {
    protected XmlAdapter() {}
    public abstract BoundType unmarshal(ValueType v, long classVersion) throws Exception;

    public abstract ValueType marshal(BoundType v, long classVersion) throws Exception;
}

Конечно, для поддержки нескольких версий нам необходимо реализовать такой адаптер и явно обрабатывать разные версии. Очевидно, что JAXB добавит специальную информацию о классе в xml и сгенерирует xml в последней версии класса.

ПРИМЕЧАНИЕ: смысл приведенного выше примера в том, что у нас есть 2 разных представления класса в персистенции одновременно, но мы все равно можем сопоставить их с версией класса, доступной во время выполнения.

Ответы [ 2 ]

1 голос
/ 28 марта 2012

JAXB означает «Архитектура Java для привязки XML», поэтому речь идет о привязке значений полей объектов к элементам / атрибутам XML, а не о сериализации объектов Java. Например, вы читаете эту статью и видите, что там написано

javax.xml.bind, содержит классы и интерфейсы для выполнения такие операции, как демаршаллинг, маршаллинг и проверка

Сериализация Java-объектов - это еще одна вещь, и она связана с serialVersionUID, который вы упоминаете в своем вопросе.

0 голосов
/ 28 марта 2012

Если вы используете JAXB, вы сохраните XML, а не объект Java.Если бы вы сохраняли объект Java, это была бы сериализация.Преобразование Jaxb пытается связать значения xml с атрибутами класса.Пока пререквизиты преобразования работают, проблем не должно быть.Другие библиотеки, такие как JIBX, пытаются напрямую получить доступ к байт-коду.Версия класса может быть проблемой в таком случае.

...