我有一些关于我的Java应用程序的设计问题。 该软件是一个桌面应用程序,它使用MySQL数据库来存储不同类型的对象(客户,员工,文档)。每个员工都有一组客户,每个客户都包含许多文档。整个结构通过hibernate延迟加载。
我目前使用这四个层来构建我的应用程序
因此,当用户现在想要向客户添加新文档时,客户视图的控制器会打开一个新的 - 让我们称之为“文档窗口”,它有自己的控制器。 由于每个文档都必须属于客户,因此我将客户作为参数传递给客户。但是,如果我使用这种方式,我必须确保打开当前的hibernate会话,并将客户对象重新连接到会话以使用延迟加载。
现在我的问题是:有更优雅的方法吗?也许通过会话级来存储当前活跃的客户?或者我的结构中有一个错误,我没有看到?
答案 0 :(得分:0)
这可能适用于数据传输对象或值对象。简而言之,在UI代码中为Customer使用只读,非休眠,分离的表示,而不是Hibernate创建的表示。此Customer对象将是您的UI所需的后端的完整Customer对象的最小投影。实际上,您可能不需要更多的名称和ID(当然取决于您的UI)。
在过去,我引入了一个“服务”界面,该界面仅适用于这些值对象或DTO(这些术语不是真正可互换,但我正在尝试要灵活,这是重要的概念: - ))。
在代表客户保存某些内容时,请调用服务组件service#attachDocument(customer.getCustomerId())
或其他任何内容。该组件将与Hibernate交互以检索客户并调用customer.addDocument(documentId)(或适用于您的模型的任何内容)。
答案 1 :(得分:0)
首先,做这样的事情并不罕见:
DocumentService {
public Document addDocument(int customerId) {
Customer customer = session.getById(Customer.class, customerId);
Document document = new Document();
customer.getDocuments().add(document);
session.update(customer);
return document;
}
}
因此,最后在添加文档之前阅读客户可能看起来像是一次性能损失,但如果您不想传递完整的Customer对象,那么这就是您的选择。
通常我会使用类似CustomerInfo对象的东西,它只存储一些相关的信息,如id,名称,地址等。通常,如果用户看到过时的数据,那些经常不变的东西并不重要。 (如果关键是经常使用通知事件/消息来更新相关的信息对象)。
现在您可以将这些CustomerInfo传递给许多常见的服务方法。如果从数据库加载了Customer对象,我通常会更新客户信息对象,以使其尽可能保持同步。
这里只有一条规则。由于客户信息可以包含陈旧数据(其他一些用户已经更改了它,因此您需要验证其有效性。您可以向其引入@Version或比较相关属性(如果已经更改)。(您使用乐观记录也称为长期用户事务和两个或多个短数据库事务。)
所以最后使用reattach没有错。
如果您有本地嵌入式数据库并且使用hibernate的应用程序是唯一的用户(单用户设置),您可能需要考虑使用单一会话方法,在该方法中同步或汇集对会话的每次访问以避免并发事务/访问数据库。
这样可以确保只有一个Object代表每个“数据库对象/行”。这使得很容易假设每个对象和每个Info都与数据库同步。只有会话丢失的情况下,您必须通过将应用程序使用的所有实体重新连接到新会话来进行恢复,以避免出现两个实体对象表示同一数据库行的情况,这在hibernate中是不允许的。
<强>摘要强>
我建议,只要你没有内存消耗问题就坚持重新安装。