JAXB和类的不同版本

时间:2012-03-28 07:20:40

标签: java xml-serialization jaxb xml-deserialization

我想知道在JAXB中是否支持不同版本的类。 我的想法:xml是类的一种持久性对象(序列化值),但是由于开发(例如扩展功能),类对象可以被改变。有没有办法知道只使用JAXB API在持久性(read:xml)中存储哪个版本的类?

对我来说,存储类版本似乎很方便 - 就像它在标准java序列化机制(我的意思是serialVersionUID)中所做的那样,并提供在类上映射xml的功能,即使在不同版本的情况下(例如添加关于类的版本的XmlAdapter信息)存储在xml中)。默认情况下,如果xml和运行时中的类版本不同 - 抛出InvalidClassException。

实施例: 我们的课程考试如下:

@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中的类版本(假设在class = 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 个答案:

答案 0 :(得分:1)

JAXB代表&#34; Java架构的XML绑定&#34;,因此,它是关于将对象字段值绑定到XML元素/属性,而不是关于序列化java对象。在您阅读此article时,您会看到它显示

  

javax.xml.bind,包含用于执行的类和接口   解组,编组和验证等操作

Java对象序列化是另一回事,它与你在问题中提到的serialVersionUID有关。

答案 1 :(得分:0)

如果您使用的是JAXB,那么您将持久化xml而不是Java对象。如果你是持久化java对象,它将是序列化。 Jaxb转换尝试将xml值绑定到类属性。只要转换先决条件有效,就不会有问题。其他库如JIBX,尝试直接访问字节码。在这种情况下,类版本可能是一个问题。