【问题标题】:JAXB and different versions of the classJAXB 和不同版本的类
【发布时间】:2012-03-28 07:20:39
【问题描述】:

我想知道 JAXB 中是否支持不同版本的类。 我对此的看法:xml 是类的一种持久性对象(序列化值),但类对象可以因开发而改变(例如扩展功能)。有什么方法可以知道仅使用 JAXB API 将哪个版本的类存储在持久性(读取:xml)中?

对我来说,存储类版本似乎很方便——就像在标准 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 () {}; 
}

现在有两种方法 - 迁移持久数据或编写将处理 Long time 并将其应用于 Date 时间的 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 种不同的类表示,但仍然可以将它们映射到运行时中可用的类版本。

【问题讨论】:

    标签: java xml-serialization jaxb xml-deserialization


    【解决方案1】:

    JAXB 代表“Java Architecture for XML Binding”,因此,它是关于将对象字段值绑定到 XML 元素/属性,而不是关于序列化 java 对象。例如,在您阅读此article 时,您会看到它说

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

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

    【讨论】:

    • 但是如果我们使用 JAX WS 作为 Web 服务实现 - JAXB API = 序列化 API。这说法不正确吗?
    • 据我所知,JAX WS 使用xjc:serializable 来覆盖实现java.io.Serializable 的类的绑定。查看JAXB 文章并搜索“xjc:serializable”。
    【解决方案2】:

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

    【讨论】:

      猜你喜欢
      • 2012-12-19
      • 2016-03-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-04-26
      • 1970-01-01
      相关资源
      最近更新 更多