2

我一直在努力寻找实现这一目标的最佳方法。假设我有两个对象,一个是用户对象,另一个是笔记对象。Note 对象将保存患者的便笺,并将存储创建便笺的人以及上次更新的人。什么是更好的选择:

选项 A - 两个对象,一个仅包含注释特定信息,另一个是此对象的扩展,其中包含患者/作者/更新者的用户对象:

public class Note {
    private int noteId;
    private int patientId;
    private int authorId;
    private int updatedById;
    private String noteText;
    private Date noteDate;
}

public class NoteExt extends Note {
    private User patient;
    private User author;
    private User updater;
}

选项 B - 一个 Note 对象,其中包含患者、作者、更新者的用户类

public class Note {
    private int noteId;
    private User patient;
    private User author;
    private User updater;
    private String noteText;
    private Date noteDate;
}

选项 A 会使应用程序膨胀,其中包含大量用于附加对象/数据库调用的文件,但在获取项目列表时会加快处理速度。(在这种情况下使用扩展也是正确的吗?)

选项 B 意味着不用担心记住何时使用哪个对象,并且只有一个数据库函数,但是如果我正在获取用户创建的所有笔记的列表,则会重复数据。

有没有更好的选项C?

4

6 回答 6

3

我不会直接将数据库基于您的数据结构。您如何在 Java 中安排数据以及如何在 DB 中安排数据不必相同,对一个有意义的可能对另一个没有意义。

于 2013-09-10T16:19:36.900 回答
2

您似乎将对象设计与数据库设计混淆了。这是可以理解的,因为您正在创建需要在数据库中表示的对象。但是,我发现在许多情况下,最简单的方法是“忘记”数据库并设计您的对象,然后使用模型映射器设计模式返回并为您的对象创建映射器,并根据需要添加唯一的 id。

因此,您使用选项 B,但用于存储/加载到数据库/从数据库加载,您使用单独的映射器类:即 UserMapper、NoteMapper 等...秘密是映射器使用 IdentityMap,以便在加载时通过 ID,使用对象的本地缓存副本,而不是一遍又一遍地访问数据库来获取用户 ID 的相同用户对象(例如)。

public class Note {
    private int noteId;
    private User patient;
    private User author;
    private User updater;
    private String noteText;
    private Date noteDate;
}

public class UserMapper {
    public User getUserById(int userId){
        User user = UserIdentityMap.getUser(userId);
        if(user == null) {
            user = fetchUserFromDb(userId);
            UserIdentifyMap.cache(userId, user);
        }
        return user;
    }
}
于 2013-09-10T19:29:27.670 回答
2

选项 B 正确。在对对象建模时,您不应该考虑如何保存数据。

于 2013-09-10T19:34:19.477 回答
2

C计划可能是这样的。使用一个组合将所有对象创建为单独的实体。使笔记更容易被其他应用程序重用。

public class Note {
    private int noteId;
    private String noteText;
    private Date noteDate;
}

public class PatientNote {
    private Note note;
    private User patient;
    private User author;
    private User updater;
}
于 2013-09-10T16:42:11.307 回答
1

根据您从数据库中检索的信息创建这样的关系,尤其是维护这种关系,并确保引用完整性,以便对一个项目的更改传播到其余项目(如果这是您想要的,否则您运行如果您不强制执行,可能会重新创建同一记录的多个副本)可能会变得非常复杂。

可能只有我一个人,但是这个NoteExt类似乎在这里滥用继承。第一堂课对我来说似乎非常好和简单,我喜欢简单。您可能会有一些数据库上下文类,应用程序可以使用它来根据其 ID(例如Database.userForId(int))查找用户或其他记录。对我来说,通过只提供必需品来保持事情的分离和简单是有意义的,但仍然提供了一种轻松请求有关记录的更多信息的方法。

正如其他人所提到的,有几个预先存在的替代方案(例如,Hibernate 和 JPA)可以为您映射数据库对象并创建您想要的那种关系。

要在下面回答您的问题,我认为重要的是要注意,我们创建的 ORM 不一定是我们为视图提供的模型——不要误会我的意思,如果总是这样就好了很容易,但是正如您所说,有时它们需要更多信息(甚至可能与数据库中的记录无关,而是与视图本身有关)。在 C# 的 MVC 框架中,我们面临一个类似的问题,我们很多人通过专门为我们的视图创建单独的模型来克服这个问题,就像 aDefaultListModel维护要在 a 中显示的数据向量JList(但模型本身并没有扩展Vector或任何其他集合)。然后,您创建的新视图模型可以包含您希望在视图中显示的所有必要信息,并提供与它交互和修改它的其他方法。

于 2013-09-10T16:33:30.183 回答
0

B 是通常的做法,JPA 已经预料到了这个问题:

  • EntityManager 充当身份映射并确保您一次不拥有多个对象的副本,因此如果您检索同一用户的笔记列表,这些将都是对同一用户对象的引用.

  • 默认情况下,对其他对象的引用是惰性的,您只能返回包含 ID 的代理,从而使开销相当于 A。

于 2013-09-10T16:33:30.320 回答