序列化对象图的一部分

时间:2010-03-30 11:42:46

标签: java serialization

我有一个关于Java自定义序列化的问题。我有一个对象图,想要配置从客户端到服务器序列化根对象时停止的位置。

让我们通过给出一个示例场景让它变得有点具体,清晰。我有类型

的类

公司
员工(摘要)
经理扩展员工 秘书扩大了员工 分析师扩展员工 项目

以下是关系:
公司(1)---(n)的雇员
经理(1) - (N)项目
分析员(1)---(n)的项目

想象一下,我在客户端,我想创建一个新公司,为其分配10名员工(新员工或现有员工)并将这家新公司发送到服务器。我期望在这种情况下将公司和所有边界员工序列化到服务器端,因为我将保存数据库上的关系。到目前为止没问题,因为默认的Java序列化机制序列化整个对象图,不包括静态或瞬态的字段。

我的目标是以下方案。想象一下,我将一家公司及其1000名员工从服务器加载到客户端。现在我只想重命名公司的名称(或其他直接属于公司的字段)并更新此记录。这次,我想只将公司对象发送到服务器端,而不是整个员工列表(我只是更新名称,员工在这个用例中无关紧要)。我的目标还包括说,转移公司和员工而不是项目关系的可配置性,你必须停在那里。

您是否知道以通用方式实现此目的的任何可能性,而不为每个实体对象实现writeObject,readObject?你的建议是什么?

我非常感谢你的回答。我对任何想法持开放态度,并准备回答你的问题,以防万一。不清楚。

3 个答案:

答案 0 :(得分:1)

您可以创建另一个类(数据传输对象),其中只有您要传输的字段。

自定义序列化的一种方法是实现Externalizable

答案 1 :(得分:0)

我会说你的问题的简短答案是否定的,如果不自己编写序列化,就不能轻易实现序列化的各种逻辑。那说一个替代方案可能是编写几个串行器/解串器对(XML,JSON,无论你最喜欢的格式,而不是标准的yusing内置序列化)。然后通过发送某种元信息序言的那些对来运行你的对象。

例如,按照上面的方案,您可能有这些(de)序列化机制对

  1. (de)serializeCompany(公司c) - 基本公司信息
  2. (de)serializeEmployee(员工e) - 了解员工的信息
  3. (de)serializeEmployee(公司c) - 公司员工的基本信息
  4. (de)serializeRelationships(公司c) - 用于项目关系
  5. 对于XML,每个都可以生成一个dom树,然后将它们全部放在包含元信息的根节点中,即

    <Company describesEmployees="true" describeRelationships="false">
    [Elements from (de)serializeCompany]
    [Elements from (de)serializeEmployee(Company c)]
    </Company>
    

    这种方法的一个潜在“问题”是确保按照您的模型以正确的顺序进行反序列化(即确保首先反序列化公司,然后是员工,然后是关系)。但是这种方法应该让你能够只编写一次“实际”序列化,然后你就可以根据这些部分的构成来构建不同的传输模型。

答案 2 :(得分:0)

您可以采用对象混合方法,通过线路将“存根”对象发送给您的客户端。

<强>赞成

  • 相同的对象图在逻辑上可用于客户端,没有序列化/反序列化不必要数据的开销。
  • 可以根据需要交换完整/存根实现,而无需更改客户端代码。

<强>缺点

  • 调用getter导致通过调用服务器动态加载其他属性的开销对客户端是隐藏的,如果你不控制客户端代码,这可能会有问题;例如不知情的用户可能会在紧密的循环中多次拨打昂贵的电话。
  • 如果您决定在客户端本地缓存数据,则需要确保它与服务器保持同步。

示例

/**
 * Lightweight company stub that only serializes the company name.
 * The collection of employees is fetched on-demand and cached locally.
 * The service responsible for returning employees must be "installed"
 * client-side when the object is first deserialized.
 */
public class CompanyStub implements Company, Serializable {
  private final String name;
  private transient Set<Employee> employees;
  private Service service;

  public Service getService() {
    return service;
  }

  public void setService(Service service) {
    this.service = service;
  }

  public String getName() {
    return name;
  }

  public Set<? extends Employee> getEmployees() {
    if (employees == null) {
      // Employees not loaded so load them now.
      this.employees = server.getEmployeesForCompany(name);
    }

    return employees;
  }
}