我知道在将 Wicket 与 JPA 框架一起使用时,不建议将已经持久保存到数据库中的实体序列化(因为惰性字段存在问题并节省空间)。在这种情况下,我们应该使用 LoadableDetachableModel。但是以下用例呢?
假设我们要创建一个新实体(例如,一个契约(Contract)),其中包括持久实体(例如,从存储在数据库中的客户列表中选择的客户)。正在创建的实体是某个 Wicket 组件(例如 Wizard)的模型对象。最后(当我们完成向导时)我们将新实体保存到数据库中。所以我的问题是:此类模型对象的序列化问题的最佳通用解决方案是什么?我们不能使用 LDM,因为该实体还不在数据库中,但我们也不希望我们的内部实体(如客户端)也被完全序列化。
我的想法是实现一个自定义 wicket 序列化程序,它检查对象是否是一个实体以及它是否持久化。如果是这样,只存储它的 id,否则使用默认序列化。同样,反序列化时使用存储的 id 并从数据库中获取实体或使用默认机制反序列化。但是,不确定如何以通用方式做到这一点。我的下一个想法是,如果我们能做到,那么我们就不再需要任何 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) 整个合约将与内部客户端一起序列化(而且它可能很大),此外,如果我们在反序列化后访问 contract.client.group,我们可能会遇到问题:https://en.wikibooks.org/wiki/Java_Persistence/Relationships#Serialization.2C_and_Detaching
所以我想知道人们是如何着手解决这些问题的,我敢肯定这是一个相当普遍的问题。
最佳答案
我想有两种方法可以解决您的问题:
a.) 仅保存用户在模型中实际看到的内容。在您的示例中,可能是“contractStartDate”、“contractEndDate”、clientIds 列表。如果您不想在 View 中显示 DatabaseObject,这是主要方法。
b.) 编写您自己的 LoadableDetachableModel 并确保您只序列化 transient 对象。例如像:(假设任何负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 将对其他实体的引用与 transient 对象分离。
在使用过这两种方法后,我个人更喜欢第一种。根据我的经验,整个将 Dao 对象注入(inject) wicket 会导致灾难。 :) 我只会在不太大的仅供查看的项目中使用它。
关于java - Wicket - 持久化和非持久化 JPA 实体的序列化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39719201/