java - 对于 Java 中的自定义对象关系映射来说,这是一个好方法吗?

标签 java object-relational-model

我正在开发一个示例 Java 应用程序,该应用程序使用 Oracle 的内置“HR”数据库模式。我想将表行视为 Java 对象。 HR 模式中的表之一 EMPLOYEES 是自引用的。它有一个 MANAGER_ID 列,其中包含(如果不为 NULL)EMPLOYEES 表中另一行的外键。

用面向对象的术语来说,问题是如何访问给定 Employee 对象的经理(这是另一个 Employee 对象)。预加载似乎不是一个好的解决方案,因为给定的 Employee 对象的经理也可能有一个经理,等等。在这种情况下,要急切加载的对象数量是无限的。

到目前为止,我决定做的是在实例化 Employee 对象时急切地加载 MANAGER_ID 字段。然后,当请求 Employee 的经理 Employee 对象时(通过 getManager() 方法),后者将被延迟加载。在代码中:

public class Employee
{
    private int id;
    private int managerId;
    private Employee manager;

    public int getId()
    {
        return id;
    }

    public Employee getManager()
    {
        if(manager == null && managerId > 0)
        {
            // Lazy loading!
        }

        return manager;
    }

    public void setManager(Employee manager)
    {
        this.manager = manager;
        this.managerId = manager.getId();
    }
}

那么这是一个好方法吗?我遇到的唯一问题是如何实现延迟加载。看起来 Employee 对象需要对其实例化器的引用——大概这与实例化其经理 Employee 对象是同一件事。

此外,我知道我可以使用众多 ORM 框架之一,而不是自行开发,但我自己这样做是为了更深入地了解底层流程。

编辑:澄清一下,我的这项工作的架构(事实上)根本不涉及 Java EE。它是一种 Java SE 架构,其中客户端通过简单的 RMI 与服务器交互。

此外,上面的 Employee 类显然需要引用 DAO 来执行延迟加载。但是,我认为这不一定是紧密耦合的,因为:

  1. Employee 对象可以保存对 DAO 实现的抽象接口(interface)的引用;和/或
  2. Employee 对象可以保存对服务器对象的引用,而服务器对象又保存对 DAO 的(私有(private))引用。

请注意,在#2 的情况下,Employee 对象引用的服务器对象可能与客户端引用的服务器对象相同。

最佳答案

如果您知道其他 ORM,为什么不研究一下它们是如何做到这一点的呢?特别是,您可能会发现 Hibernate 的延迟加载代理很有趣:

Hibernate 将创建(在运行时,使用字节码生成)Employee 的子类,它封装对尚未加载的员工对象的引用。调用此类上的任何方法(getId() 除外)都会加载引用的员工对象,然后委托(delegate)给它。

与您的方法相比,这具有不需要为每个关联编码延迟加载支持的优点,而是可以为所有关联编码一次,从而避免数据库访问代码污染域模型(托管业务逻辑)。此外,只要调用者不访问对象的状态,就可以在不加载对象的情况下使用该对象。例如,他们可以这样做:

void switchJobs(Employee e1, Employee e2) {
    Employee m1 = e1.getManager();  // doesn't load the manager!
    e1.setManager(e2.getManager()); // doesn't load the manager!
    e2.setManager(m1);
}

此外,Hibernate 不会在一个事务中多次加载同一个管理器,而是重用已加载的持久对象或延迟加载代理。这既提高了性能,又提高了对象模型的一致性,即,如果多名员工共享一个经理,并且一名员工修改了该经理,另一名员工将看到该更改,并且可以使用 == 来比较经理。

关于java - 对于 Java 中的自定义对象关系映射来说,这是一个好方法吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4423080/

相关文章:

java 杀进程一段时间后

Java 泛型 PECS

java - java读取txt文件中的分数

java.time 和 JPA

python - 我为 Neo4j 做的 Python 对象映射是否太天真了?

database - 使用对象关系数据库(如 Oracle/PostrgreSQL)与常规关系数据库的好处?

database - 如何在 oracle11g 中定义引用该类型集合的类型?

Java ArrayList、LinkedList 和 Stack 问题

sql - 什么是扩展 SQL 模式?