Wicket - 持久化和非持久化JPA实体的序列化

时间:2016-09-27 07:58:09

标签: java jpa serialization wicket

我知道在使用Wicket和JPA框架时,不建议将已经持久化的实体序列化到数据库中(因为存在惰性字段问题并节省空间)。在这种情况下,我们应该使用LoadableDetachableModel。但是以下用例呢?

假设我们想要创建一个新实体(比如契约),其中包括持久化实体(例如,从存储在数据库中的客户列表中选择的客户端)。创建中的实体是某个Wicket组件的模型对象(例如,向导)。最后(当我们完成向导时),我们将新实体保存到DB。所以我的问题是:这种模型对象的序列化问题的最佳通用解决方案是什么?我们无法使用LDM,因为该实体尚未在数据库中,但我们也不希望我们的内部实体(如客户端)也完全被序列化。

我的想法是实现一个自定义wicket序列化程序,用于检查对象是否是实体以及是否持久化。如果是,则仅存储其id,否则使用默认序列化。类似地,反序列化时使用存储的id并从DB获取实体或使用默认机制反序列化。但是,不确定如何以通用的方式做到这一点。我的下一个想法是,如果我们能够做到,那么我们就不再需要任何LDM了,我们可以将所有实体存储在简单的org.apache.wicket.model.Model模型中,我们的序列化逻辑将处理它们,对吧?

这里有一些代码:

  @Entity
  Client {
     String clientName;

     @ManyToOne(fetch = FetchType.LAZY)
     ClientGroup group;
  }

  @Entity
  Contract {
     Date date;

     @ManyToOne(fetch = FetchType.LAZY)
     Client client;
  }

  ContractWizard extends Wizard {
     ContractWizard(String markupId, IModel<Contract> model) {
        super(markupId);
        setDefaultModel(model);
     }
  }

  Contract contract = DAO.createEntity(Contract.class);
  ContractWizard wizard = new ContractWizard("wizard", ?); 

如何通过合同?如果我们只说Model.of(契约),整个合同将与内部客户一起序列化(并且它可能很大),而且如果我们在反序列化后访问contract.client.group我们可以遇到问题:{{3} }

所以我想知道人们如何解决这些问题,我确信这是一个相当普遍的问题。

2 个答案:

答案 0 :(得分:1)

我想你的问题有2种方法:

a。)仅保存用户在模型中实际看到的内容。在您的示例中,可能是&#34; contractStartDate&#34;,&#34; contractEndDate&#34;,clientIds列表。如果您不希望在视图中使用DatabaseObject,那么这是主要方法。

b。)编写自己的LoadableDetachableModel并确保只序列化瞬态对象。例如:(假设任何否定ID都没有保存到数据库中)

public class MyLoadableDetachableModel extends LoadableDetachableModel {

private Object myObject;

private Integer id;

public MyLoadableDetachableModel(Object myObject) {
    this.myObject = myObject;
    this.id = myObject.getId();
}

@Override
protected Object load() {
    if (id < 0) {
        return myObject;
    }

    return myObjectDao.getMyObjectById(id);
}

@Override
protected void onDetach() {
    super.onDetach();
    id = myObject.getId();

    if (id >= 0) {
        myObject = null;
    }
}
}

这种情况的失败是你必须使你的DatabaseObjects Serializable不是很理想,并且可能导致各种问题。您还需要使用ListModel将对其他实体的引用与瞬态对象分离。

使用这两种方法后,我个人更喜欢第一种方法。从我的expierence整个注入dao对象到wicket可能导致灾难。 :)我只会在只有视图的项目中使用它,这些项目并不太大。

答案 1 :(得分:0)

我所知道的大多数项目只接受序列化被引用实体(例如您的客户)以及已编辑的实体(合同)。

使用对话(在多个请求中保持Hibernate / JPA会话打开)对于具有复杂实体关系的应用程序来说是一个不错的选择: Hibernate会话及其实体与页面分开,永远不会被序列化。该组件只保留一个标识符来获取其对话。