我知道在使用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} }
所以我想知道人们如何解决这些问题,我确信这是一个相当普遍的问题。
答案 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会话及其实体与页面分开,永远不会被序列化。该组件只保留一个标识符来获取其对话。